class sale_order_line(osv.osv): def _number_packages(self, cr, uid, ids, field_name, arg, context=None): res = {} for line in self.browse(cr, uid, ids, context=context): try: res[line.id] = int((line.product_uom_qty+line.product_packaging.qty-0.0001) / line.product_packaging.qty) except: res[line.id] = 1 return res _inherit = 'sale.order.line' _columns = { 'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation and the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}), 'procurement_id': fields.many2one('procurement.order', 'Procurement'), 'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}), 'product_packaging': fields.many2one('product.packaging', 'Packaging'), 'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True), 'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'), } _defaults = { 'delay': 0.0, 'product_packaging': False, } def _get_line_qty(self, cr, uid, line, context=None): if line.procurement_id and not (line.order_id.invoice_quantity=='order'): return self.pool.get('procurement.order').quantity_get(cr, uid, line.procurement_id.id, context=context) else: return super(sale_order_line, self)._get_line_qty(cr, uid, line, context=context) def _get_line_uom(self, cr, uid, line, context=None): if line.procurement_id and not (line.order_id.invoice_quantity=='order'): return self.pool.get('procurement.order').uom_get(cr, uid, line.procurement_id.id, context=context) else: return super(sale_order_line, self)._get_line_uom(cr, uid, line, context=context) def button_cancel(self, cr, uid, ids, context=None): res = super(sale_order_line, self).button_cancel(cr, uid, ids, context=context) for line in self.browse(cr, uid, ids, context=context): for move_line in line.move_ids: if move_line.state != 'cancel': raise osv.except_osv( _('Cannot cancel sales order line!'), _('You must first cancel stock moves attached to this sales order line.')) return res def copy_data(self, cr, uid, id, default=None, context=None): if not default: default = {} default.update({'move_ids': []}) return super(sale_order_line, self).copy_data(cr, uid, id, default, context=context) def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, partner_id=False, packaging=False, flag=False, context=None): if not product: return {'value': {'product_packaging': False}} product_obj = self.pool.get('product.product') product_uom_obj = self.pool.get('product.uom') pack_obj = self.pool.get('product.packaging') warning = {} result = {} warning_msgs = '' if flag: res = self.product_id_change(cr, uid, ids, pricelist=pricelist, product=product, qty=qty, uom=uom, partner_id=partner_id, packaging=packaging, flag=False, context=context) warning_msgs = res.get('warning') and res['warning']['message'] products = product_obj.browse(cr, uid, product, context=context) if not products.packaging: packaging = result['product_packaging'] = False elif not packaging and products.packaging and not flag: packaging = products.packaging[0].id result['product_packaging'] = packaging if packaging: default_uom = products.uom_id and products.uom_id.id pack = pack_obj.browse(cr, uid, packaging, context=context) q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty, default_uom) # qty = qty - qty % q + q if qty and (q and not (qty % q) == 0): ean = pack.ean or _('(n/a)') qty_pack = pack.qty type_ul = pack.ul if not warning_msgs: warn_msg = _("You selected a quantity of %d Units.\n" "But it's not compatible with the selected packaging.\n" "Here is a proposition of quantities according to the packaging:\n" "EAN: %s Quantity: %s Type of ul: %s") % \ (qty, ean, qty_pack, type_ul.name) warning_msgs += _("Picking Information ! : ") + warn_msg + "\n\n" warning = { 'title': _('Configuration Error!'), 'message': warning_msgs } result['product_uom_qty'] = qty return {'value': result, 'warning': warning} def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None): context = context or {} product_uom_obj = self.pool.get('product.uom') partner_obj = self.pool.get('res.partner') product_obj = self.pool.get('product.product') warning = {} res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id, lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context) if not product: res['value'].update({'product_packaging': False}) return res #update of result obtained in super function product_obj = product_obj.browse(cr, uid, product, context=context) res['value']['delay'] = (product_obj.sale_delay or 0.0) res['value']['type'] = product_obj.procure_method #check if product is available, and if not: raise an error uom2 = False if uom: uom2 = product_uom_obj.browse(cr, uid, uom) if product_obj.uom_id.category_id.id != uom2.category_id.id: uom = False if not uom2: uom2 = product_obj.uom_id # Calling product_packaging_change function after updating UoM res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context) res['value'].update(res_packing.get('value', {})) warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or '' compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding) if (product_obj.type=='product') and int(compare_qty) == -1 \ and (product_obj.procure_method=='make_to_stock'): warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \ (qty, uom2 and uom2.name or product_obj.uom_id.name, max(0,product_obj.virtual_available), product_obj.uom_id.name, max(0,product_obj.qty_available), product_obj.uom_id.name) warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n" #update of warning messages if warning_msgs: warning = { 'title': _('Configuration Error!'), 'message' : warning_msgs } res.update({'warning': warning}) return res
def _save_file(self, path, b64_file): """Save a file encoded in base 64""" self._check_filestore(path) with open(path, 'w') as ofile: ofile.write(base64.b64decode(b64_file)) return True def _set_image(self, cr, uid, id, name, value, arg, context=None): image = self.browse(cr, uid, id, context=context) full_path = self._image_path(cr, uid, image, context=context) if full_path: return self._save_file(full_path, value) return self.write(cr, uid, id, {'file_db_store' : value}, context=context) _columns = { 'name':fields.char('Image Title', size=100, required=True), 'extention': fields.char('file extention', size=6), 'link':fields.boolean('Link?', help="Images can be linked from files on your file system or remote (Preferred)"), 'file_db_store':fields.binary('Image stored in database'), 'file':fields.function(_get_image, fnct_inv=_set_image, type="binary", filters='*.png,*.jpg,*.gif'), 'url':fields.char('File Location', size=250), 'comments':fields.text('Comments'), 'product_id':fields.many2one('product.product', 'Product') } _defaults = { 'link': lambda *a: False, } _sql_constraints = [('uniq_name_product_id', 'UNIQUE(product_id, name)', _('A product can have only one image with the same name'))]
user_id = res[0] elif conf['create_user']: _logger.debug("Creating new Odoo user \"%s\" from LDAP" % login) user_obj = self.pool['res.users'] values = self.map_ldap_attributes(cr, uid, conf, login, ldap_entry) if conf['user']: values['active'] = True user_id = user_obj.copy(cr, SUPERUSER_ID, conf['user'], default=values) else: user_id = user_obj.create(cr, SUPERUSER_ID, values) return user_id _columns = { 'sequence': fields.integer('Sequence'), 'company': fields.many2one('res.company', 'Company', required=True, ondelete='cascade'), 'ldap_server': fields.char('LDAP Server address', required=True), 'ldap_server_port': fields.integer('LDAP Server port', required=True), 'ldap_binddn': fields.char('LDAP binddn', help=("The user account on the LDAP server that is used to query " "the directory. Leave empty to connect anonymously.")), 'ldap_password': fields.char('LDAP password', help=("The password of the user account on the LDAP server that is " "used to query the directory.")), 'ldap_filter': fields.char('LDAP filter', required=True), 'ldap_base': fields.char('LDAP base', required=True), 'user': fields.many2one('res.users', 'Template User', help="User to copy when creating new users"), 'create_user': fields.boolean('Create user', help="Automatically create local user accounts for new users authenticating via LDAP"), 'ldap_tls': fields.boolean('Use TLS',
try: price = grid_obj.get_price(cr, uid, carrier_grid, order, time.strftime("%Y-%m-%d"), context) available = True except osv.except_osv, e: # no suitable delivery method found, probably configuration error _logger.error("Carrier %s: %s\n%s" % (carrier.name, e.name, e.value)) price = 0.0 else: price = 0.0 res[carrier.id] = {"price": price, "available": available} return res _columns = { "name": fields.char("Delivery Method", required=True), "partner_id": fields.many2one( "res.partner", "Transport Company", required=True, help="The partner that is doing the delivery service." ), "product_id": fields.many2one("product.product", "Delivery Product", required=True), "grids_id": fields.one2many("delivery.grid", "carrier_id", "Delivery Grids"), "available": fields.function( get_price, string="Available", type="boolean", multi="price", help="Is the carrier method possible with the current order.", ), "price": fields.function(get_price, string="Price", multi="price"), "active": fields.boolean( "Active", help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it.", ),
} def onchange_shipping_service(self, cr, uid, ids, ups_shipper_id=False, context=None): vals = {} service_type_ids = [] if ups_shipper_id: shipper_obj = self.pool.get('ups.account.shipping').browse(cr, uid, ups_shipper_id) for shipper in shipper_obj.ups_shipping_service_ids: service_type_ids.append(shipper.id) domain = [('id', 'in', service_type_ids)] return {'domain': {'ups_service_id': domain}} _columns= { 'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64), 'ups_shipper_id': fields.many2one('ups.account.shipping', 'Shipper'), 'ups_service_id': fields.many2one('ups.shipping.service.type', 'Shipping Service'), 'ups_pickup_type': fields.selection([ ('01', 'Daily Pickup'), ('03', 'Customer Counter'), ('06', 'One Time Pickup'), ('07', 'On Call Air'), ('11', 'Suggested Retail Rates'), ('19', 'Letter Center'), ('20', 'Air Service Center'), ], 'Pickup Type'), 'ups_packaging_type': fields.many2one('shipping.package.type','Packaging Type'), 'partner_id': fields.many2one('res.partner', 'Customer'), 'partner_shipping_id': fields.many2one('res.partner', 'Shipping Address'), } shipping_rate_wizard()
>>>>>>> c1979f64b3360c86d60e00c92be0271d89f97f2d 'cc_number':fields.char('Credit Card Number', size=256), 'cc_v':fields.char('Card Code Verification', size=3), 'cc_e_d_month':fields.char('Expiration Date MM', size=32), 'cc_e_d_year':fields.char('Expiration Date YY', size=32), 'cc_comment':fields.char('Comment', size=128,), 'cc_auth_code':fields.char('Authorization Code', size=32), 'cc_save_card_details':fields.boolean('Save Credit Card details'), 'cc_ecommerce_sale':fields.boolean('Ecommerce sale'), 'cc_p_authorize':fields.boolean('Pre-authorize'), 'cc_charge':fields.boolean('Charge'), 'cc_info_hide':fields.boolean('Credit Info Hide'), 'cc_status':fields.text('Status Message'), 'cc_details_autofill':fields.boolean('Credit Card Details Auto Fill'), 'cc_reseller':fields.boolean('Reseller'), 'rel_sale_order_id':fields.many2one('sale.order', 'Related Sale Order'), 'cc_trans_id':fields.char('Transaction ID', size=128), 'cc_bank':fields.many2one('res.bank', 'Bank'), 'cc_details':fields.many2one('res.partner.bank', 'Bank'), 'cc_length':fields.integer('CC Length'), 'cc_transaction':fields.boolean('Transaction Done'), 'key':fields.char('Encryption Key', size=1024, help="The Key used to Encrypt the Credit Card Number"), 'cc_refund_amt':fields.float('Refund Amt'), 'is_charged': fields.boolean('CreditCard Charged'), 'trans_history_ids': fields.one2many('transaction.details', 'voucher_id', 'Transaction History') } _defaults = { 'cc_info_hide': lambda * a: True, 'cc_p_authorize': lambda * a: True, }
if 'Expecting: CERTIFICATE' in e[0]: raise osv.except_osv( _('Wrong Certificate file format'), _('Be sure you have BEGIN CERTIFICATE string in' ' your first line.')) else: raise osv.except_osv( _('Unknown error'), _('X509 return this message:\n %s') % e[0]) wz.wsafip_request_id.write({'state': 'confirmed'}) _name = 'l10n_ar_wsafip.loadcert_config' _inherit = 'res.config' _columns = { 'wsafip_request_id': fields.many2one( 'crypto.certificate', 'Certificate Request', required=True), 'wsafip_request_file': fields.binary( 'Download Signed Certificate Request', readonly=True), 'wsafip_request_filename': fields.char( 'Filename', readonly=True), 'wsafip_response_file': fields.binary( 'Upload Certificate', required=True), } _defaults = { 'wsafip_request_filename': 'request.csr', } l10n_ar_wsafip_loadcert_config() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class sale_order_line(orm.Model): _inherit = "sale.order.line" def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None): context = context or self.pool['res.users'].context_get(cr, uid) vals = super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id, context) if vals: vals.update({'origin_document': 'sale.order.line, {line_id}'.format(line_id=line.id)}) return vals def _delivered_qty(self, cr, uid, ids, field_name, arg, context=None): context = context or self.pool['res.users'].context_get(cr, uid) res = {} for line in self.browse(cr, uid, ids, context=context): qty = 0 for move in line.move_ids: if move.state == 'done': qty += move.product_qty res[line.id] = qty return res def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None): """ Finds the incoming and outgoing quantity of product. @return: Dictionary of values """ context = context or self.pool['res.users'].context_get(cr, uid) res = {} # if line.order_id: # context['warehouse'] = self.order_id.shop_id.warehouse_id.id for line in self.browse(cr, uid, ids, context): res[line.id] = { 'qty_available': line.product_id and line.product_id.type != 'service' and line.product_id.qty_available or False, 'virtual_available': line.product_id and line.product_id.type != 'service' and line.product_id.virtual_available or False} return res # overwrite of a funcion inside sale_margin def product_id_change(self, cr, uid, ids, pricelist, product_id, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None): context = context or self.pool['res.users'].context_get(cr, uid) context.update(error_on_available=False) res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product_id, qty=qty, uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id, lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context) if not pricelist: return res frm_cur = self.pool['res.users'].browse(cr, uid, uid, context).company_id.currency_id.id to_cur = self.pool['product.pricelist'].browse(cr, uid, [pricelist], context)[0].currency_id.id if product_id: product = self.pool['product.product'].browse(cr, uid, product_id, context) price = self.pool['res.currency'].compute(cr, uid, frm_cur, to_cur, product.cost_price, round=False) res['value'].update({ 'purchase_price': price, 'product_type': product.type }) return res _columns = { 'order_id': fields.many2one('sale.order', 'Order Reference', ondelete='cascade', select=True, readonly=True, states={'draft': [('readonly', False)]}), 'readonly_price_unit': fields.related('order_id', 'company_id', 'readonly_price_unit', type='boolean', string=_('Readonly Price Unit'), store=False, readonly=True), 'delivered_qty': fields.function(_delivered_qty, digits_compute=dp.get_precision('Product UoM'), string='Delivered Qty'), 'qty_available': fields.function(_product_available, multi='qty_available', type='float', digits_compute=dp.get_precision('Product UoM'), string='Quantity On Hand'), 'virtual_available': fields.function(_product_available, multi='qty_available', type='float', digits_compute=dp.get_precision('Product UoM'), string='Quantity Available'), 'product_type': fields.char('Product type', size=64), } _defaults = { 'readonly_price_unit': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context).company_id.readonly_price_unit, 'order_id': lambda self, cr, uid, context: context.get('default_sale_order', False) or False } def default_get(self, cr, uid, fields, context=None): """ """ if not context: context = self.pool['res.users'].context_get(cr, uid) res = super(sale_order_line, self).default_get(cr, uid, fields, context=context) if not res.get('tax_id', False): fpos_obj = self.pool['account.fiscal.position'] product_default_get = self.pool['product.product'].default_get(cr, uid, ['taxes_id', 'uom_id']) taxes = product_default_get.get('taxes_id', False) if taxes: taxes = self.pool['account.tax'].browse(cr, uid, taxes, context) if context.get('fiscal_position', False): fpos = fpos_obj.browse(cr, uid, context['fiscal_position'], context) if taxes: tax_id = fpos_obj.map_tax(cr, uid, fpos, taxes) else: tax_id = [] else: if taxes: tax_id = [line.id for line in taxes] else: tax_id = [] res.update({ 'tax_id': [(6, 0, tax_id)], }) uom_id = product_default_get.get('uom_id', False) if uom_id: res.update({ 'product_uom': uom_id }) return res
class ids_emp_info_change(osv.osv): _name = 'ids.emp.info.change' _description = "Employee Information Change" def _employee_get(self, cr, uid, context=None): """Gets default value from the hr.employee. """ emp_id = context.get('default_employee_id', False) if emp_id: return emp_id ids = self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)], context=context) if ids: return ids[0] return False _columns = { 'name':fields.char('Name', size=100), 'division_id':fields.many2one('division', 'Division'), 'emp_code':fields.char('Employee Code', size=100), 'employee_id':fields.many2one('hr.employee','Employee Name'), 'req_date':fields.date('Request Date'), 'date':fields.date('Date'), 'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'), 'doa':fields.date('Date Of Anniversary'), 'email':fields.char('Email', size=240), 'blood_groups':fields.selection([('1','A+'),('2','B+'),('3','A-'),('4','B-'),('5','O+'),('6','O-'),('7','AB+'),('8','AB-')], 'Blood Group'), 'mobile_no':fields.char('Mobile', size=240), 'home_phone':fields.char('Home Phone', size=240), 'local_address':fields.char('Local Address'), 'pin_local':fields.char('Pin', size=100), 'permanent_address':fields.char('Permanent Address'), 'pin_permanent':fields.char('Pin', size=100), 'weight':fields.char('Weight', size=100), 'height':fields.char('Height', size=100), 'passport_no':fields.char('Passport No.', size=100), 'passport_till':fields.date('Passport Till'), 'vehicle':fields.char('Vehicle'), 'hobby':fields.char('Hobby'), 'spouse_name':fields.char('Spouse Name'), 'child_name1':fields.char('Child Name'), 'dob1':fields.date('DOB'), 'child_name2':fields.char('Child Name'), 'dob2':fields.date('DOB'), 'emerg_per_name':fields.char('Emergency Person Name'), 'emerg_per_relation':fields.char('Emergency Person Relation'), 'emerg_address':fields.char('Emergency Address'), 'emerg_pin':fields.char('Emergency Pin'), 'emerg_contact_no':fields.char('Emergency Contact Number'), 'text1':fields.char('Text1'), 'text2':fields.char('Text2'), 'text3':fields.char('Text3'), 'text4':fields.char('Text4'), 'text5':fields.char('Text5'), 'text6':fields.char('Text6'), 'text7':fields.char('Text7'), 'text8':fields.char('Text8'), 'text9':fields.char('Text9'), 'text10':fields.char('Text10'), 'text11':fields.char('Text11'), 'text12':fields.char('Text12'), 'text13':fields.char('Text13'), 'text14':fields.char('Text14'), 'text15':fields.char('Text15'), 'text16':fields.char('Text16'), 'text17':fields.char('Text17'), 'text18':fields.char('Text18'), 'text19':fields.char('Text19'), 'text20':fields.char('Text20'), 'text21':fields.char('Text21'), 'text22':fields.char('Text22'), 'text23':fields.char('Text23'), 'text24':fields.char('Text24'), 'text25':fields.char('Text25'), 'text26':fields.char('Text26'), 'marital_prev': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'), 'doa_prev':fields.date('Date Of Anniversary'), 'email_prev':fields.char('Email', size=240), 'blood_groups_prev':fields.selection([('1','A+'),('2','B+'),('3','A-'),('4','B-'),('5','O+'),('6','O-'),('7','AB+'),('8','AB-')], 'Blood Group'), 'mobile_no_prev':fields.char('Mobile', size=240), 'home_phone_prev':fields.char('Home Phone', size=240), 'local_address_prev':fields.char('Local Address'), 'pin_local_prev':fields.char('Pin', size=100), 'permanent_address_prev':fields.char('Permanent Address'), 'pin_permanent_prev':fields.char('Pin', size=100), 'weight_prev':fields.char('Weight', size=100), 'height_prev':fields.char('Height', size=100), 'passport_no_prev':fields.char('Passport No.', size=100), 'passport_till_prev':fields.date('Passport Till'), 'vehicle_prev':fields.char('Vehicle'), 'hobby_prev':fields.char('Hobby'), 'spouse_name_prev':fields.char('Spouse Name'), 'child_name1_prev':fields.char('Child Name'), 'dob1_prev':fields.date('DOB'), 'child_name2_prev':fields.char('Child Name'), 'dob2_prev':fields.date('DOB'), 'emerg_per_name_prev':fields.char('Emergency Person Name'), 'emerg_per_relation_prev':fields.char('Emergency Person Relation'), 'emerg_address_prev':fields.char('Emergency Address'), 'emerg_pin_prev':fields.char('Emergency Pin'), 'emerg_contact_no_prev':fields.char('Emergency Contact Number'), 'state': fields.selection([ ('draft', 'Draft'), ('submitted', 'Waiting For Approval'), ('validated', 'Approved'), ('refused', 'Refused'), ], 'Status', readonly=True, help='When the employee information change request is created the status is \'Draft\'.\n It is submitted by the employee and request is sent to Location HR, the status is \'submitted\'.\ \nIf the Location Hr validate it, the status is \'Validated\'.\n If the Location Hr refuse it, the status is \'Refused\'.'), } _defaults = { 'employee_id': _employee_get, 'state': 'draft', 'req_date': lambda *a: time.strftime("%Y-%m-%d"), } def unlink(self, cr, uid, ids, context=None): for item in self.browse(cr, uid, ids, context=context): if item.state not in ('draft'): raise osv.except_osv(_('Warning!'),_('You cannot delete a request which is not draft!')) return super(ids_emp_info_change, self).unlink(cr, uid, ids, context=context) def onchange_employee_id(self, cr, uid, ids, employee_id, context=None): """Get all the values associated with employee with onchange of employee id from hr.employee. """ emp_code = '' marital = '' doa = '' email = '' blood_group = '' mobile_no = '' home_phone = '' local_address = '' pin_local = '' permanent_address = '' pin_permanent = '' weight = '' height = '' passport_no = '' passport_till = '' vehicle = '' hobby = '' spouse_name = '' child_name1 = '' dob1 = '' child_name2 = '' dob2 = '' emerg_per_name = '' emerg_per_relation = '' emerg_address = '' emerg_pin = '' emerg_contact_no = '' division_id='' obj_emp = self.pool.get('hr.employee') res={} if employee_id: record = obj_emp.browse(cr,uid,employee_id,context=context) if record: emp_code = record.emp_code marital = record.marital doa = record.marriage_date email = record.work_email blood_group = record.blood_groups mobile_no = record.mobile_phone home_phone = record.work_phone permanent_address = record.permanent_address weight = record.weight height = record.height passport_no = record.passport_id local_address = record.current_address division_id=record.division res = {'value': { 'emp_code': emp_code, 'marital': marital, 'email': email, 'blood_groups': blood_group, 'mobile_no': mobile_no, 'home_phone': home_phone, 'permanent_address': permanent_address, 'weight': weight, 'height': height, 'passport_no': passport_no, 'local_address' : local_address, 'doa' : doa, 'marital_prev': marital, 'email_prev': email, 'blood_groups_prev': blood_group, 'mobile_no_prev': mobile_no, 'home_phone_prev': home_phone, 'permanent_address_prev': permanent_address, 'weight_prev': weight, 'height_prev': height, 'passport_no_prev': passport_no, 'local_address_prev' : local_address, 'doa_prev' : doa, 'division_id': division_id } } return res def submit(self, cr, uid, ids, context=None): """Submit the form to Location HR. """ change=self.browse(cr, uid, ids, context=context) if change.marital<>change.marital_prev: self.write(cr, uid, ids, {'text1': 'Update'}, context=context) if change.email<>change.email_prev: self.write(cr, uid, ids, {'text2': 'Update'}, context=context) if change.mobile_no<>change.mobile_no_prev: self.write(cr, uid, ids, {'text3': 'Update'}, context=context) if change.local_address<>change.local_address_prev: self.write(cr, uid, ids, {'text4': 'Update'}, context=context) if change.permanent_address<>change.permanent_address_prev: self.write(cr, uid, ids, {'text5': 'Update'}, context=context) if change.weight<>change.weight_prev: self.write(cr, uid, ids, {'text6': 'Update'}, context=context) if change.passport_no<>change.passport_no_prev: self.write(cr, uid, ids, {'text7': 'Update'}, context=context) if change.vehicle<>change.vehicle_prev: self.write(cr, uid, ids, {'text8': 'Update'}, context=context) if change.child_name1<>change.child_name1_prev: self.write(cr, uid, ids, {'text9': 'Update'}, context=context) if change.child_name2<>change.child_name2_prev: self.write(cr, uid, ids, {'text10': 'Update'}, context=context) if change.emerg_per_name<>change.emerg_per_name_prev: self.write(cr, uid, ids, {'text11': 'Update'}, context=context) if change.emerg_address<>change.emerg_address_prev: self.write(cr, uid, ids, {'text12': 'Update'}, context=context) if change.emerg_contact_no<>change.emerg_contact_no_prev: self.write(cr, uid, ids, {'text13': 'Update'}, context=context) if change.doa<>change.doa_prev: self.write(cr, uid, ids, {'text14': 'Update'}, context=context) if change.blood_groups<>change.blood_groups_prev: self.write(cr, uid, ids, {'text15': 'Update'}, context=context) if change.home_phone<>change.home_phone_prev: self.write(cr, uid, ids, {'text16': 'Update'}, context=context) if change.pin_local<>change.pin_local_prev: self.write(cr, uid, ids, {'text17': 'Update'}, context=context) if change.pin_permanent<>change.pin_permanent_prev: self.write(cr, uid, ids, {'text18': 'Update'}, context=context) if change.height<>change.height_prev: self.write(cr, uid, ids, {'text19': 'Update'}, context=context) if change.passport_till<>change.passport_till_prev: self.write(cr, uid, ids, {'text20': 'Update'}, context=context) if change.hobby<>change.hobby_prev: self.write(cr, uid, ids, {'text21': 'Update'}, context=context) if change.dob1<>change.dob1_prev: self.write(cr, uid, ids, {'text22': 'Update'}, context=context) if change.dob2<>change.dob2_prev: self.write(cr, uid, ids, {'text23': 'Update'}, context=context) if change.emerg_per_relation<>change.emerg_per_relation_prev: self.write(cr, uid, ids, {'text24': 'Update'}, context=context) if change.emerg_pin<>change.emerg_pin_prev: self.write(cr, uid, ids, {'text25': 'Update'}, context=context) if change.spouse_name<>change.spouse_name_prev: self.write(cr, uid, ids, {'text26': 'Update'}, context=context) url="http://ids-erp.idsil.loc:8069/web" if change.mobile_no<>change.mobile_no_prev or change.local_address<>change.local_address_prev: values = { 'subject': 'Employee Information Change Request', 'body_html': change.employee_id.display_name + ' ' + 'created change request for Mobile No./Local Address.<br/> Please take necessary action.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/><br/>Url:'+url, 'email_to': change.employee_id.division.hr_email, 'email_cc': change.employee_id.parent_id.work_email, 'email_from': '*****@*****.**', } else: values = { 'subject': 'Employee Information Change Request', 'body_html': change.employee_id.display_name + ' ' + 'created change request . <br/>Please take necessary action.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/><br/>Url:'+url, 'email_to': change.employee_id.division.hr_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) print"mail sent successfully======" return self.write(cr, uid, ids, {'state': 'submitted'}, context=context) def validate(self, cr, uid, ids, context=None): """Validation Process """ change=self.browse(cr, uid, ids, context=context) if change.marital<>change.marital_prev: self.write(cr, uid, ids, {'text1': 'Updated'}, context=context) if change.email<>change.email_prev: self.write(cr, uid, ids, {'text2': 'Updated'}, context=context) if change.mobile_no<>change.mobile_no_prev: self.write(cr, uid, ids, {'text3': 'Updated'}, context=context) if change.local_address<>change.local_address_prev: self.write(cr, uid, ids, {'text4': 'Updated'}, context=context) if change.permanent_address<>change.permanent_address_prev: self.write(cr, uid, ids, {'text5': 'Updated'}, context=context) if change.weight<>change.weight_prev: self.write(cr, uid, ids, {'text6': 'Updated'}, context=context) if change.passport_no<>change.passport_no_prev: self.write(cr, uid, ids, {'text7': 'Updated'}, context=context) if change.vehicle<>change.vehicle_prev: self.write(cr, uid, ids, {'text8': 'Updated'}, context=context) if change.child_name1<>change.child_name1_prev: self.write(cr, uid, ids, {'text9': 'Updated'}, context=context) if change.child_name2<>change.child_name2_prev: self.write(cr, uid, ids, {'text10': 'Updated'}, context=context) if change.emerg_per_name<>change.emerg_per_name_prev: self.write(cr, uid, ids, {'text11': 'Updated'}, context=context) if change.emerg_address<>change.emerg_address_prev: self.write(cr, uid, ids, {'text12': 'Updated'}, context=context) if change.emerg_contact_no<>change.emerg_contact_no_prev: self.write(cr, uid, ids, {'text13': 'Updated'}, context=context) if change.doa<>change.doa_prev: self.write(cr, uid, ids, {'text14': 'Updated'}, context=context) if change.blood_groups<>change.blood_groups_prev: self.write(cr, uid, ids, {'text15': 'Updated'}, context=context) if change.home_phone<>change.home_phone_prev: self.write(cr, uid, ids, {'text16': 'Updated'}, context=context) if change.pin_local<>change.pin_local_prev: self.write(cr, uid, ids, {'text17': 'Updated'}, context=context) if change.pin_permanent<>change.pin_permanent_prev: self.write(cr, uid, ids, {'text18': 'Updated'}, context=context) if change.height<>change.height_prev: self.write(cr, uid, ids, {'text19': 'Updated'}, context=context) if change.passport_till<>change.passport_till_prev: self.write(cr, uid, ids, {'text20': 'Updated'}, context=context) if change.hobby<>change.hobby_prev: self.write(cr, uid, ids, {'text21': 'Updated'}, context=context) if change.dob1<>change.dob1_prev: self.write(cr, uid, ids, {'text22': 'Updated'}, context=context) if change.dob2<>change.dob2_prev: self.write(cr, uid, ids, {'text23': 'Updated'}, context=context) if change.emerg_per_relation<>change.emerg_per_relation_prev: self.write(cr, uid, ids, {'text24': 'Updated'}, context=context) if change.emerg_pin<>change.emerg_pin_prev: self.write(cr, uid, ids, {'text25': 'Updated'}, context=context) if change.spouse_name<>change.spouse_name_prev: self.write(cr, uid, ids, {'text26': 'Updated'}, context=context) email=change.employee_id.work_email emp_obj=self.pool.get('hr.employee') emp_id=emp_obj.search(cr, uid, [('id','=',change.employee_id.id)]) emp_data = emp_obj.browse(cr, uid, emp_id) if emp_data: emp_obj.write(cr, uid, emp_data.id, { 'marital': change.marital, 'marriage_date': change.doa, 'work_email': change.email, 'blood_groups': change.blood_groups, 'mobile_phone': change.mobile_no, 'work_phone': change.home_phone, 'permanent_address': change.permanent_address, 'weight': change.weight, 'height': change.height, 'passport_id': change.passport_no, 'current_address': change.local_address,}, context=context) url="http://ids-erp.idsil.loc:8069/web" if change.mobile_no<>change.mobile_no_prev or change.local_address<>change.local_address_prev: values = { 'subject': 'Employee Information Change Request', 'body_html': 'Your change request for Mobile No./Local Address is approved.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/><br/>Url:'+url, 'email_to': email, 'email_cc': change.employee_id.parent_id.work_email, 'email_from': '*****@*****.**', } else: values = { 'subject': 'Information Change Request Status', 'body_html': 'Your change request is approved.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/><br/>Url:'+url, 'email_to': email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) date = time.strftime("%Y-%m-%d"), return self.write(cr, uid, ids, {'state': 'validated','date': date}, context=context) def refuse(self, cr, uid, ids, context=None): """In case, Form get refused. """ change=self.browse(cr, uid, ids, context=context) if change.marital<>change.marital_prev: self.write(cr, uid, ids, {'text1': 'Not Updated'}, context=context) if change.email<>change.email_prev: self.write(cr, uid, ids, {'text2': 'Not Updated'}, context=context) if change.mobile_no<>change.mobile_no_prev: self.write(cr, uid, ids, {'text3': 'Not Updated'}, context=context) if change.local_address<>change.local_address_prev: self.write(cr, uid, ids, {'text4': 'Not Updated'}, context=context) if change.permanent_address<>change.permanent_address_prev: self.write(cr, uid, ids, {'text5': 'Not Updated'}, context=context) if change.weight<>change.weight_prev: self.write(cr, uid, ids, {'text6': 'Not Updated'}, context=context) if change.passport_no<>change.passport_no_prev: self.write(cr, uid, ids, {'text7': 'Not Updated'}, context=context) if change.vehicle<>change.vehicle_prev: self.write(cr, uid, ids, {'text8': 'Not Updated'}, context=context) if change.child_name1<>change.child_name1_prev: self.write(cr, uid, ids, {'text9': 'Not Updated'}, context=context) if change.child_name2<>change.child_name2_prev: self.write(cr, uid, ids, {'text10': 'Not Updated'}, context=context) if change.emerg_per_name<>change.emerg_per_name_prev: self.write(cr, uid, ids, {'text11': 'Not Updated'}, context=context) if change.emerg_address<>change.emerg_address_prev: self.write(cr, uid, ids, {'text12': 'Not Updated'}, context=context) if change.emerg_contact_no<>change.emerg_contact_no_prev: self.write(cr, uid, ids, {'text13': 'Not Updated'}, context=context) if change.doa<>change.doa_prev: self.write(cr, uid, ids, {'text14': 'Not Updated'}, context=context) if change.blood_group<>change.blood_group_prev: self.write(cr, uid, ids, {'text15': 'Not Updated'}, context=context) if change.home_phone<>change.home_phone_prev: self.write(cr, uid, ids, {'text16': 'Not Updated'}, context=context) if change.pin_local<>change.pin_local_prev: self.write(cr, uid, ids, {'text17': 'Not Updated'}, context=context) if change.pin_permanent<>change.pin_permanent_prev: self.write(cr, uid, ids, {'text18': 'Not Updated'}, context=context) if change.height<>change.height_prev: self.write(cr, uid, ids, {'text19': 'Not Updated'}, context=context) if change.passport_till<>change.passport_till_prev: self.write(cr, uid, ids, {'text20': 'Not Updated'}, context=context) if change.hobby<>change.hobby_prev: self.write(cr, uid, ids, {'text21': 'Not Updated'}, context=context) if change.dob1<>change.dob1_prev: self.write(cr, uid, ids, {'text22': 'Not Updated'}, context=context) if change.dob2<>change.dob2_prev: self.write(cr, uid, ids, {'text23': 'Not Updated'}, context=context) if change.emerg_per_relation<>change.emerg_per_relation_prev: self.write(cr, uid, ids, {'text24': 'Not Updated'}, context=context) if change.emerg_pin<>change.emerg_pin_prev: self.write(cr, uid, ids, {'text25': 'Not Updated'}, context=context) if change.spouse_name<>change.spouse_name_prev: self.write(cr, uid, ids, {'text26': 'Not Updated'}, context=context) email=change.employee_id.work_email url="http://ids-erp.idsil.loc:8069/web" if change.mobile_no<>change.mobile_no_prev or change.local_address<>change.local_address_prev: values = { 'subject': 'Employee Information Change Request', 'body_html': 'Your change request for Mobile No./Local Address is refused . <br/>Please Contact to your HR department.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/><br/>Url:'+url, 'email_to': email, 'email_cc': change.employee_id.parent_id.work_email, 'email_from': '*****@*****.**', } else: values = { 'subject': 'Information Change Request Status', 'body_html': 'Your change request is refused .<br/> Please Contact to your HR department.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/><br/>Url:'+url, 'email_to': email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) date = time.strftime("%Y-%m-%d"), return self.write(cr, uid, ids, {'state': 'refused','date': date}, context=context)
class session (osv.Model): _name = 'openacademy.session' _inherit = ['mail.thread', 'ir.needaction_mixin'] def compute_available_seats(self, seats, attendee_ids): if seats == 0 or len(attendee_ids) > seats: return 0.0 else: return 100.0 - (float(len(attendee_ids)) / seats * 100) def get_available_seats(self, cr, uid, ids, field, arg, context={}): res = {} sessions = self.browse(cr, uid, ids, context=context) for session in sessions: res[session.id] = self.compute_available_seats(session.seats, session.attendee_ids) return res def onchange_seats(self, cr, uid, ids, seats, attendee_ids, context={}): res = { 'value': { 'available_seats': self.compute_available_seats(seats, attendee_ids) } } if seats < 0: res['warning'] = { 'title': _('Warning: wrong value'), 'message': _('The seats number cannot be negative.') } elif seats < len(attendee_ids): res['warning'] = { 'title': _('Warning: wrong value'), 'message': _('There is not enough seats for everyone.') } return res def _compute_end_date(self, cr, uid, ids, fields, arg, context={}): res = {} for session in self.browse(cr, uid, ids, context=context): if session.start_date and session.duration: start_date = datetime.strptime(session.start_date, "%Y-%m-%d") duration = timedelta(days=(session.duration-1)) end_date = start_date + duration res[session.id] = end_date.strftime('%Y-%m-%d') else: res[session.id] = session.start_date return res def _set_end_date(self, cr, uid, id, field, value, arg, context={}): session = self.browse(cr, uid, id, context=context) if session.start_date and value: start_date = datetime.strptime(session.start_date, "%Y-%m-%d") end_date = datetime.strptime(value[:10], "%Y-%m-%d") duration = end_date - start_date self.write(cr, uid, id, {'duration': (duration.days + 1)}, context=context) def _compute_hours(self, cr, uid, ids, fields, arg, context={}): res = {} for session in self.browse(cr, uid, ids, context=context): res[session.id] = (session.duration * 24 if session.duration else 0) """ if session.duration: res[session.id] = session.duration * 24 else: res[session.id] = 0 """ return res def _compute_attendee_count(self, cr, uid, ids, fields, arg, context={}): res = {} for session in self.browse(cr, uid, ids, context=context): res[session.id] = len(session.attendee_ids) return res def _set_hours(self, cr, uid, id, field, value, arg, context={}): if value: self.write(cr, uid, id, {'duration':(value/24)}, context=context) def action_draft(self, cr, uid, ids, context={}): return self.write(cr, uid, ids, {'state': 'draft'}, context=context) def action_confirmed(self, cr, uid, ids, context={}): return self.write(cr, uid, ids, {'state': 'confirmed'}, context=context) def action_done(self, cr, uid, ids, context={}): return self.write(cr, uid, ids, {'state': 'done'}, context=context) _columns = { 'name': fields.char(string="Name", size=128, required=True, translate=True), 'start_date': fields.date(string="Start date"), 'duration': fields.float(string="Duration", digits=(6,2), help="Session durantion in days"), 'seats': fields.integer(string="Number of seats"), 'instructor_id':fields.many2one('res.partner', string="Instructor", ondelete="set null", domain="['|',('instructor','=',True),('category_id.name','in',['Teacher level 1', 'Teacher level 2'])]"), 'course_id': fields.many2one('openacademy.course', string="Course", ondelete="cascade"), 'attendee_ids': fields.one2many('openacademy.attendee', 'session_id', string="Attendees"), 'available_seats': fields.function(get_available_seats, type="float", string="Available Seats (%)", readonly=True), 'active': fields.boolean(string="Active", help="Uncheck this to deactivate this session. Beware, it will not appear anymore in the session list."), 'end_date': fields.function(_compute_end_date, fnct_inv=_set_end_date, type="date", string="End date"), 'hours': fields.function(_compute_hours, fnct_inv=_set_hours, type="float", string="Hours"), 'attendee_count': fields.function(_compute_attendee_count, type="integer", string="Attendee Count", store=True), 'color': fields.integer('Color'), 'state': fields.selection([('draft','Draft'),('confirmed','Confirmed'),('done','Done')], string="State"), } _defaults = { 'start_date': fields.date.today, 'active': True, 'state': 'draft', } def _check_instructor_not_in_attendees(self, cr, uid, ids, context={}): for session in self.browse(cr, uid, ids, context=context): #partners = [] #for attendee in session.attendee_ids: # partners.append(attendee.partner_id) partners = [attendee.partner_id for attendee in session.attendee_ids] if session.instructor_id and session.instructor_id in partners: return False return True _constraints = [ (_check_instructor_not_in_attendees, "The instructor cannot be also an attendee.", ['instructor_id', 'attendee_ids']) ]
class sale_order(orm.Model): _inherit = "sale.order" def default_get(self, cr, uid, fields, context=None): context = context or self.pool['res.users'].context_get(cr, uid) # sale_order_obj = self.pool['sale.order'] # sale_order_line_obj = self.pool['sale.order.line'] res = super(sale_order, self).default_get(cr, uid, fields, context=context) if not res.get('shop_id', False): shop_ids = self.pool['sale.order'].search(cr, uid, [], limit=1, context=context) if shop_ids: res['shop_id'] = shop_ids[0] if not res.get('section_id', False): section_ids = self.pool['crm.case.section'].search(cr, uid, [('user_id', '=', uid)], context=context) if section_ids: res['section_id'] = section_ids[0] return res def service_only(self, cr, uid, ids, context): context = context or self.pool['res.users'].context_get(cr, uid) service = True if not isinstance(ids, (list, tuple)): ids = [ids] for order in self.browse(cr, uid, ids, context): if order.order_line: for order_line in order.order_line: if order_line.product_id and order_line.product_id.type != 'service': return False elif not service: return False return True def hook_sale_state(self, cr, uid, orders, vals, context): context = context or self.pool['res.users'].context_get(cr, uid) # function call if change state the sale order return True def adaptative_function(self, cr, uid, ids, vals, context): context = context or self.pool['res.users'].context_get(cr, uid) if not isinstance(ids, (list, tuple)): ids = [ids] if vals.get('section_id', False) or vals.get('carrier_id', False) or vals.get('payment_term'): for order in self.browse(cr, uid, ids, context): partner_vals = {} if not order.partner_id.section_id: partner_vals['section_id'] = vals.get('section_id') if not order.partner_id.property_delivery_carrier: partner_vals['property_delivery_carrier'] = vals.get('carrier_id') if not order.partner_id.property_payment_term: partner_vals['property_payment_term'] = vals.get('payment_term') if partner_vals: self.pool['res.partner'].write(cr, uid, [order.partner_id.id], partner_vals, context) return True def create(self, cr, uid, vals, context=None): context = context or self.pool['res.users'].context_get(cr, uid) ids = super(sale_order, self).create(cr, uid, vals, context=context) self.adaptative_function(cr, uid, ids, vals, context) return ids def write(self, cr, uid, ids, vals, context=None): if context is None: context = self.pool['res.users'].context_get(cr, uid) if not isinstance(ids, (list, tuple)): ids = [ids] orders = self.browse(cr, uid, ids, context) self.adaptative_function(cr, uid, ids, vals, context) if vals.get('state', False): self.hook_sale_state(cr, uid, orders, vals, context) return super(sale_order, self).write(cr, uid, ids, vals, context=context) def action_wait(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context): company = self.pool['res.users'].browse(cr, uid, uid).company_id if self.service_only(cr, uid, [order.id], context) and order.order_policy and order.order_policy == 'picking': if company.auto_order_policy: order.write({'order_policy': 'manual'}) else: raise orm.except_orm(_('Warning'), _( "You can't create an order with Invoicing being based on Picking if there are only service products")) else: if company.auto_order_policy: default = self.default_get(cr, uid, ['order_policy'], context) order.write({'order_policy': default.get('order_policy')}) return super(sale_order, self).action_wait(cr, uid, ids, context) def copy(self, cr, uid, ids, default, context=None): context = context or self.pool['res.users'].context_get(cr, uid) default.update( { 'tech_validation': False, 'manager_validation': False, 'customer_validation': False, 'email_sent_validation': False, 'supervisor_validation': False, 'date_order': fields.date.context_today, } ) default.update(self.default_get(cr, uid, ['order_policy', 'picking_policy', 'invoice_quantity'], context)) return super(sale_order, self).copy(cr, uid, ids, default, context) def action_cancel_draft(self, cr, uid, ids, *args): self.write(cr, uid, ids, { 'tech_validation': False, 'manager_validation': False, 'customer_validation': False, 'email_sent_validation': False, 'supervisor_validation': False, }) super(sale_order, self).action_cancel_draft(cr, uid, ids, *args) return True def onchange_invoice_type_id(self, cr, uid, ids, invoice_type_id, context=None): if context is None: context = self.pool['res.users'].context_get(cr, uid) res = {} if invoice_type_id: invoice_type_obj = self.pool['sale_journal.invoice.type'] invoice_type = invoice_type_obj.browse(cr, uid, invoice_type_id, context) if invoice_type.invoicing_method == 'grouped': res['order_policy'] = 'picking' return {'value': res} def onchange_partner_id(self, cr, uid, ids, part, context=None): context = context or self.pool['res.users'].context_get(cr, uid) res = super(sale_order, self).onchange_partner_id(cr, uid, ids, part) if res.get('value', False) and part: if not res['value'].get('fiscal_position', False): company_id = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.id company = self.pool['res.company'].browse(cr, uid, company_id, context) if company.default_property_account_position: res['value']['fiscal_position'] = company.default_property_account_position and company.default_property_account_position.id return res def _credit_limit(self, cr, uid, ids, field_name, arg, context): context = context or self.pool['res.users'].context_get(cr, uid) res = dict.fromkeys(ids, 0.0) for order in self.browse(cr, uid, ids, context=context): if order.order_policy == 'prepaid': res[order.id] = 0 continue partner = order.partner_id credit = partner.credit # We sum from all the sale orders that are aproved, the sale order lines that are not yet invoiced order_obj = self.pool['sale.order'] approved_invoices_ids = order_obj.search(cr, uid, [('partner_id', '=', partner.id), ('state', 'not in', ['draft', 'cancel', 'done'])], context=context) approved_invoices_amount = 0.0 for orders in order_obj.browse(cr, uid, approved_invoices_ids, context=context): for order_line in orders.order_line: if not order_line.invoiced: approved_invoices_amount += order_line.price_subtotal # We sum from all the invoices that are in draft the total amount invoice_obj = self.pool['account.invoice'] draft_invoices_ids = invoice_obj.search(cr, uid, [('partner_id', '=', partner.id), ('state', '=', 'draft')], context=context) draft_invoices_amount = 0.0 for invoice in invoice_obj.browse(cr, uid, draft_invoices_ids, context=context): draft_invoices_amount += invoice.amount_total available_credit = partner.credit_limit - credit - approved_invoices_amount - draft_invoices_amount res[order.id] = available_credit - order.amount_total return res def partner_overdue_check(self, cr, uid, company, partner, context): # return True if there are same overdue payment account_move_line_obj = self.pool['account.move.line'] overdue_date = (datetime.today() - relativedelta(days=company.date_max_overdue or 0.0)).strftime(DEFAULT_SERVER_DATE_FORMAT) account_move_ids = account_move_line_obj.search(cr, uid, [ ('partner_id', '=', partner.id), ('account_id.type', 'in', ['receivable', 'payable']), ('stored_invoice_id', '!=', False), ('reconcile_id', '=', False), ('date_maturity', '<', overdue_date)], context=context) if account_move_ids: return True return False def check_limit(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context=context): if order.credit_limit < 0 and order.company_id and order.company_id.check_credit_limit: title = _(u'Credit Over Limit') msg = _(u'Is not possible to confirm because customer exceed the credit limit. \n Is Possible change the Order Policy \"Pay Before Delivery\" \n on tab \"Other Information\"') raise orm.except_orm(_(title), _(msg)) return False if order.visible_minimum and order.sale_order_minimun > order.amount_untaxed: if order.shop_id.user_allow_minimun_id and order.shop_id.user_allow_minimun_id.id == uid: # if user can validate return True # test if on line there are the product if order.shop_id.product_allow_minimun_id: for line in order.order_line: if line.product_id and line.product_id == order.shop_id.product_allow_minimun_id: return True title = _(u'Minimum Amount Billable') if order.shop_id.user_allow_minimun_id: msg = _(u'Is not possible to confirm because is not reached the minimum billable {amount} {currency} \n Only {user} can do it').format(amount=order.sale_order_minimun, currency=order.pricelist_id.currency_id.symbol, user=order.shop_id.user_allow_minimun_id.name) else: msg = _(u'Is not possible to confirm because is not reached the minimum billable {amount} {currency}').format(amount=order.sale_order_minimun, currency=order.pricelist_id.currency_id.symbol) if order.shop_id.product_allow_minimun_id: msg += _(u'\n\n or add the product \'{product}\'').format(product=order.shop_id.product_allow_minimun_id.name_get()[0][1]) raise orm.except_orm(_(title), _(msg)) return False if order.company_id and order.company_id.check_overdue: if self.partner_overdue_check(cr, uid, order.company_id, order.partner_id, context): title = _(u'Overdue Limit') msg = _(u'Is not possible to confirm because customer have a overdue payment') raise orm.except_orm(_(title), _(msg)) return False return True def name_get(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) if not len(ids): return [] res = [] for sale in self.browse(cr, uid, ids, context=context): name = u'[{sale_name}] {partner_name}'.format(sale_name=sale.name, partner_name=sale.partner_id.name) res.append((sale.id, name)) return res def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=10): context = context or self.pool['res.users'].context_get(cr, uid) if not args: args = [] if name: ids = self.search(cr, uid, [('name', operator, name)] + args, limit=limit, context=context) if not len(ids): ids = self.search(cr, uid, [('partner_id', 'ilike', name)] + args, limit=limit, context=context) ids = list(set(ids)) if not len(ids): ptrn = re.compile('(\[(.*?)\])') res = ptrn.search(name) if res: ids = self.search( cr, uid, [('name', '=', res.group(2))] + args, limit=limit, context=context) else: ids = self.search(cr, uid, args, limit=limit, context=context) result = self.name_get(cr, uid, ids, context=context) return result def __init__(self, registry, cr): """ Add state "Suspended" """ super(sale_order, self).__init__(registry, cr) options = [('wait_technical_validation', _('Technical Validation')), ('wait_manager_validation', _('Manager Validation')), ('send_to_customer', _('Send To Customer')), ('wait_customer_validation', _('Customer Validation')), ('wait_supervisor_validation', _('Supervisor Validation'))] type_selection = self._columns['state'].selection for option in options: if option not in type_selection: type_selection.append(option) def _get_shop_id(self, cr, uid, context): shop_ids = self.pool['sale.shop'].search(cr, uid, [], context=context, limit=1) return shop_ids and shop_ids[0] or False _columns = { 'create_uid': fields.many2one('res.users', 'Created by', readonly=True), 'credit_limit': fields.function(_credit_limit, string="Remaining Credit Limit", type='float', readonly=True, method=True), 'sale_order_minimun': fields.related('shop_id', 'sale_order_minimun', type='float', string='Minimun Invoice', store=False, readonly=True), 'visible_minimum': fields.related('shop_id', 'sale_order_have_minimum', type='boolean', string=_('Minimun Amount'), store=False, readonly=True), 'visible_credit_limit': fields.related('company_id', 'check_credit_limit', type='boolean', string=_('Fido Residuo Visibile'), store=False, readonly=True), 'validity': fields.date('Validity'), 'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={ 'draft': [('readonly', False)], 'wait_technical_validation': [('readonly', False)], 'wait_manager_validation': [('readonly', False)]} ), 'project_id': fields.many2one('account.analytic.account', 'Contract/Analytic Account', readonly=True, states={ 'draft': [('readonly', False)], 'wait_technical_validation': [('readonly', False)], 'wait_manager_validation': [('readonly', False)], 'send_to_customer': [('readonly', False)], 'wait_customer_validation': [('readonly', False)], }, help="The analytic account related to a sales order."), 'required_tech_validation': fields.related('company_id', 'need_tech_validation', type='boolean', string=_('Required Technical Validation'), store=False, readonly=True), 'need_tech_validation': fields.boolean("Technical Validation", readonly=True), 'tech_validation': fields.boolean("Tech Validated ?", readonly=True), 'required_manager_validation': fields.related('company_id', 'need_manager_validation', type='boolean', string=_('Required Manager Validation'), store=False, readonly=True), 'need_manager_validation': fields.boolean("Manager Validation", readonly=True), 'manager_validation': fields.boolean("Manager Validated ?", readonly=True), 'email_sent_validation': fields.boolean("Email Sent to Customer ?", readonly=True), 'customer_validation': fields.boolean("Customer Validated ?", readonly=True), # A validation after customer confirmation: 'required_supervisor_validation': fields.related('company_id', 'need_supervisor_validation', type='boolean', string=_('Required Supervisor Validation'), store=False, readonly=True), 'skip_supervisor_validation_onstandard_product': fields.related('company_id', 'skip_supervisor_validation_onstandard_product', type='boolean', string=_( 'Skip Supervisor Verification if there are only standard product'), store=False, readonly=True), 'supervisor_validation': fields.boolean(_("Supervisor Validated?"), readonly=True), 'product_id': fields.related('order_line', 'product_id', type='many2one', relation='product.product', string='Product'), 'revision_note': fields.char('Reason', size=256, select=True), 'lost_reason_id': fields.many2one('crm.lost.reason', string='Lost Reason'), 'last_revision_note': fields.related('sale_version_id', 'revision_note', type='char', string="Last Revision Note", store=True), } _defaults = { 'need_tech_validation': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context).company_id.need_tech_validation, 'need_manager_validation': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context).company_id.need_manager_validation, 'skip_supervisor_validation_onstandard_product': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context).company_id.skip_supervisor_validation_onstandard_product, 'required_tech_validation': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context).company_id.need_tech_validation, 'required_manager_validation': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context).company_id.need_manager_validation, 'required_supervisor_validation': lambda self, cr, uid, context: self.pool['res.users'].browse(cr, uid, uid, context).company_id.need_supervisor_validation, 'validity': lambda self, cr, uid, context: (datetime.today() + relativedelta(days=self.pool['res.users'].browse(cr, uid, uid, context).company_id.default_sale_order_validity or 0.0)).strftime(DEFAULT_SERVER_DATE_FORMAT), 'shop_id': lambda self, cr, uid, context: self._get_shop_id(cr, uid, context), } def action_reopen(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) result = super(sale_order, self).action_reopen(cr, uid, ids, context=context) for order in self.browse(cr, uid, ids, context): if order.state == 'draft': self.write(cr, uid, ids, { 'tech_validation': False, 'manager_validation': False, 'email_sent_validation': False, 'customer_validation': False, }, context) return result def check_direct_order_confirm(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context): if order.state == 'draft' and order.pricelist_id and order.pricelist_id.contract: return True else: return False def check_tech_validation(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context): if order.shop_id.user_tech_validation_id: if order.shop_id.user_tech_validation_id.id == uid: return True else: title = _('Technical Validation') msg = _(u"It's not possible to confirm, for shop {shop} only user '{user}' can do it".format(shop=order.shop_id.name, user=order.shop_id.user_tech_validation_id.name)) raise orm.except_orm(_(title), _(msg)) return False else: return True def check_manager_validation(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context): if order.shop_id.user_manager_validation_id: if order.shop_id.user_manager_validation_id.id == uid: return True else: title = _('Manager Validation') msg = _(u"It's not possible to confirm, for shop {shop} only user '{user}' can do it".format(shop=order.shop_id.name, user=order.shop_id.user_manager_validation_id.name)) raise orm.except_orm(_(title), _(msg)) return False else: return True def check_supervisor_validation(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context): if order.shop_id.user_supervisor_validation_id: if order.shop_id.user_supervisor_validation_id.id == uid: return True else: title = _('Supervisor Validation') msg = _(u"It's not possible to confirm, for shop {shop} only user '{user}' can do it".format(shop=order.shop_id.name, user=order.shop_id.user_supervisor_validation_id.name)) raise orm.except_orm(_(title), _(msg)) return False else: return True def required_tech_validation(self, order): if order.company_id.tech_validation_if_no_product: for line in order.order_line: if not line.product_id: order.write({'need_tech_validation': True}) return True return False def check_discount(self, order): if order.company_id.enable_discount_validation: max_discount = order.company_id.max_discount for line in order.order_line: if line.discount > max_discount: order.write({'need_manager_validation': True}) return True return False def action_validate(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context): if not order.partner_id.validate and order.company_id.enable_partner_validation: title = _('Partner To Validate') msg = _("It's not possible to confirm because customer must be validated") raise orm.except_orm(_(title), _(msg)) return False if order.need_tech_validation and not order.tech_validation or self.required_tech_validation(order): vals = { 'state': 'wait_technical_validation', } elif self.check_discount(order): vals = { 'state': 'wait_manager_validation', } elif order.company_id.enable_margin_validation and order.amount_untaxed and (order.margin / order.amount_untaxed) * 100 < order.company_id.minimum_margin and not order.manager_validation: vals = { 'state': 'wait_manager_validation', } elif order.need_manager_validation and not order.manager_validation: vals = { 'state': 'wait_manager_validation', } elif not order.email_sent_validation: vals = { 'state': 'send_to_customer', } elif not order.customer_validation: vals = { 'state': 'wait_customer_validation', } elif order.required_supervisor_validation and not order.supervisor_validation: vals = { 'state': 'wait_supervisor_validation', } else: vals = { 'state': 'draft', 'tech_validation': False, 'manager_validation': False, 'customer_validation': False, 'email_sent_validation': False, 'supervisor_validation': False } order.write(vals) return True def check_validate(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for order in self.browse(cr, uid, ids, context): res = True if order.need_tech_validation and not order.tech_validation: res = False elif order.need_manager_validation and not order.manager_validation: res = False elif order.required_supervisor_validation and not order.supervisor_validation: if order.skip_supervisor_validation_onstandard_product: for line in order.order_line: if line.product_id and line.product_id.is_kit: return False res = True else: res = False return res and order.email_sent_validation and order.customer_validation return True def check_direct_confirm(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) if self.check_limit(cr, uid, ids, context): for order in self.browse(cr, uid, ids, context): values = { 'state': 'wait_customer_validation', 'customer_validation': True } if order.need_tech_validation: values['tech_validation'] = True if (order.company_id.enable_margin_validation and order.amount_untaxed and (order.margin / order.amount_untaxed) < order.company_id.minimum_margin) or order.need_manager_validation: values['manager_validation'] = True if order.required_supervisor_validation: values['supervisor_validation'] = True self.write(cr, uid, [order.id], values, context) return self.action_validate(cr, uid, ids, context) else: return False def copy(self, cr, uid, ids, default={}, context=None): default = default or {} context = context or self.pool['res.users'].context_get(cr, uid) default.update({ 'validity': (datetime.today() + relativedelta(days=self.pool['res.users'].browse(cr, uid, uid, context).company_id.default_sale_order_validity or 0.0)).strftime(DEFAULT_SERVER_DATE_FORMAT), 'tech_validation': False, 'manager_validation': False, 'customer_validation': False, 'email_sent_validation': False, 'supervisor_validation': False, 'lost_reason_id': False }) return super(sale_order, self).copy(cr, uid, ids, default, context=context)
class Message(osv.Model): #TODO: turn off for data import only _log_access = True _name = "message.message" _order = "write_date desc,sequence" _description = 'UPDIS Message' _inherit = ['mail.thread', 'ir.needaction_mixin'] def _default_fbbm(self, cr, uid, context=None): employee_ids = self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)]) if employee_ids: return self.pool.get('hr.employee').browse(cr, uid, employee_ids[0]).department_id.name def _default_department(self, cr, uid, context=None): employee_ids = self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)]) if employee_ids: return self.pool.get('hr.employee').browse(cr, uid, employee_ids[0]).department_id.id def _get_image(self, cr, uid, ids, name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): result[obj.id] = tools.image_get_resized_images(obj.image) return result def _set_image(self, cr, uid, id, field_name, value, args, context=None): return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context) def _get_name_display(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): result[obj.id] = obj.is_display_name and obj.create_uid.name or u'匿名用户' return result def _get_message_meta_display(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): message_meta = '' if obj.category_id.message_meta: env = Env(cr, uid, 'message.message', [obj.id]) message_meta = eval(obj.category_id.message_meta, env, nocopy=True) result[obj.id] = message_meta return result def _get_category_message_title_meta_display(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): category_message_title_meta = '' if obj.category_id.category_message_title_meta: env = Env(cr, uid, 'message.message', [obj.id]) category_message_title_meta = eval(obj.category_id.category_message_title_meta, env, nocopy=True) result[obj.id] = category_message_title_meta return result def _get_create_date_display(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): if obj.create_date: create_date_display = datetime.datetime.strptime(obj.create_date, '%Y-%m-%d %H:%M:%S') + datetime.timedelta(hours=8) result[obj.id] = create_date_display.strftime('%Y-%m-%d %H:%M:%S') return result def _get_write_date_display(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): if obj.write_date: write_date_display = datetime.datetime.strptime(obj.write_date, '%Y-%m-%d %H:%M:%S') + datetime.timedelta(hours=8) result[obj.id] = write_date_display.strftime('%Y-%m-%d %H:%M:%S') return result def _get_shorten_name(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): size = obj.category_id.category_message_title_size title = len(obj.name) > size and obj.name[:size] + '...' or obj.name result[obj.id] = title return result def _get_message_list_meta_display(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): message_meta = '' if obj.category_id.message_meta: env = Env(cr, uid, 'message.message', [obj.id]) message_meta = eval(obj.category_id.phone_message_list_meta, env, nocopy=True) result[obj.id] = message_meta return result def _get_message_detail_meta_display(self, cr, uid, ids, field_name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): category_message_title_meta = '' if obj.category_id.category_message_title_meta: env = Env(cr, uid, 'message.message', [obj.id]) category_message_title_meta = eval(obj.category_id.phone_message_detail_meta, env, nocopy=True) result[obj.id] = category_message_title_meta return result def _get_vote_count(self, cr, uid, ids, field_name, args, context=None): """ Either way, it must return a dictionary of values of the form {'id_1_': 'value_1_', 'id_2_': 'value_2_',...}. If multi is set, then field_name is replaced by field_names: a list of the field names that should be calculated. Each value in the returned dictionary is also a dictionary from field name to value. For example, if the fields 'name', and 'age' are both based on the vital_statistics function, then the return value of vital_statistics might look like this when ids is [1, 2, 5]: { 1: {'name': 'Bob', 'age': 23}, 2: {'name': 'Sally', 'age', 19}, 5: {'name': 'Ed', 'age': 62} } """ result = dict.fromkeys(ids, False) message_vote_obj = self.pool.get('message.vote') for message in self.browse(cr, uid, ids, context=context): vote_like_count = len(message_vote_obj.search(cr, SUPERUSER_ID, [('message_id', '=', message.id), ('up', '=', True)], context)) vote_unlike_count = len(message_vote_obj.search(cr, SUPERUSER_ID, [('message_id', '=', message.id), ('up', '=', False)], context)) result[message.id] = { 'vote_like': vote_like_count, 'vote_unlike': vote_unlike_count, } return result _columns = { 'name': fields.char("Title", size=128, required=True), 'shorten_name': fields.function(_get_shorten_name, type="char", size=256, string="Shorten title"), 'message_meta_display': fields.function(_get_message_meta_display, type="char", size=256, string="Meta"), 'category_message_title_meta_display': fields.function(_get_category_message_title_meta_display, type="char", size=256, string="Category meta"), 'message_list_meta_display': fields.function(_get_message_list_meta_display, type="char", size=256, string="Phone Message List Meta"), 'message_detail_meta_display': fields.function(_get_message_detail_meta_display, type="char", size=256, string="Phone Message Detail meta"), 'category_id': fields.many2one('message.category', 'Category', required=True, change_default=True), 'content': fields.text("Content"), 'sequence': fields.integer("Display Sequence"), 'is_display_name': fields.boolean('Display name?'), 'fbbm': fields.char('Publisher', size=128), 'read_times': fields.integer("Read Times"), 'expire_date': fields.date('Expire Date'), 'create_date': fields.datetime('Created on', select=True ,readonly=True), 'department_id': fields.many2one("hr.department", "Department", domain=[('deleted', '=', False)]), 'create_uid': fields.many2one('res.users', 'Author', select=True, readonly=True), 'write_date': fields.datetime('Modification date', select=True , readonly=True), 'write_uid': fields.many2one('res.users', 'Last Contributor', select=True , readonly=True), 'source': fields.char("Message Source", size=128), 'name_for_display': fields.function(_get_name_display, type="char", size=64, string="Name"), 'sms_receiver_ids': fields.many2many("hr.employee", "message_hr_employee_rel", "message_id", "hr_employee_id", "SMS Receiver"), 'sms': fields.text('SMS', size=140), 'is_allow_send_sms': fields.related('category_id', 'is_allow_send_sms', type="boolean", string="Allow send SMS?"), 'is_allow_sms_receiver': fields.related('category_id', 'is_allow_send_sms', type="boolean", string="Allow specify sms receiver?"), 'category_id_name': fields.related('category_id', 'name', type="char", string="category name"), 'category_id_is_anonymous_allowed': fields.related('category_id', 'is_anonymous_allowed', type="boolean", string="category is anonymous allowed"), 'category_id_is_allowed_edit_sms_text': fields.related('category_id', 'is_allowed_edit_sms_text', type="boolean", string="category is allowed edit sms text"), 'create_date_display': fields.function(_get_create_date_display, type="datetime", string="Create Date Display", readonly=True), 'write_date_display': fields.function(_get_write_date_display, type="datetime", string="Write Date Display", readonly=True), 'vote_user_ids': fields.many2many('res.users', 'message_vote', 'message_id', 'user_id', string='Votes', help='Users that voted for this message'), 'vote_like': fields.function(_get_vote_count, type="integer", string='Like', multi='vote'), 'vote_unlike': fields.function(_get_vote_count, type='integer', string='Unlike', multi='vote'), } _defaults = { 'fbbm': _default_fbbm, 'department_id': _default_department, 'is_display_name': True, } def onchange_category(self, cr, uid, ids, category_id, context=None): ret = {'value': {}} if category_id: message_category = self.pool.get('message.category').browse(cr, uid, category_id) sms_vals = { 'is_allow_send_sms': message_category.is_allow_send_sms, 'is_allow_sms_receiver': message_category.is_allow_sms_receiver, 'sms_receiver_ids': [x.id for x in message_category.default_sms_receiver_ids], 'category_id_name': message_category.name, 'category_id_is_anonymous_allowed': message_category.is_anonymous_allowed, 'category_id_is_allowed_edit_sms_text': message_category.is_allowed_edit_sms_text, } ret['value'].update(sms_vals) return ret #abandon def onchange_name(self, cr, uid, ids, name, sms, context=None): ret = {'value': {}} if not sms: name_vals = { 'sms': name, } if not len(ids): ret['value'].update(name_vals) return ret def create(self, cr, uid, vals, context=None): if context is None: context = {'mail_create_nolog': True} else: context.update({'mail_create_nolog': True}) if self._log_access is True: if not vals['category_id_is_allowed_edit_sms_text']: vals['sms'] = vals['name'] mid = super(Message, self).create(cr, uid, vals, context) sms = self.pool.get('sms.sms') message = self.pool.get('message.message').browse(cr, uid, mid, context=context) if message.is_allow_send_sms: to = ','.join( [rid.mobile_phone.strip() for rid in message.sms_receiver_ids if rid.mobile_phone and rid.mobile_phone.strip()]) if to: content = message.sms and message.category_id.name + ':' + message.sms or message.category_id.name + ':' + message.name sid = sms.create(cr, uid, {'to': to, 'content': content, 'model': 'message.message', 'res_id': mid}, context=context) else: mid = super(Message, self).create(cr, uid, vals, context) return mid def write(self, cr, uid, ids, vals, context=None): #get message old position if self._log_access is True: TYPE = [] if not (len(vals) == 1 and 'read_times' in vals.keys()): messages_old = self.pool.get('message.message').browse(cr, 1, ids, context=context) for message_old in messages_old: if message_old.category_id.display_position == 'shortcut': TYPE.append('0') if message_old.category_id.display_position == 'content_left': TYPE.append('1') if message_old.category_id.display_position == 'content_right': TYPE.append('2') TYPE = set(TYPE) super(Message, self).write(cr, uid, ids, vals, context=context) NEW_TYPE = [] #refresh cms page if not (len(vals) == 1 and 'read_times' in vals.keys()): #get message new position messages = self.pool.get('message.message').browse(cr, 1, ids, context=context) for message in messages: if message.category_id.display_position == 'shortcut': NEW_TYPE.append('0') if message.category_id.display_position == 'content_left': NEW_TYPE.append('1') if message.category_id.display_position == 'content_right': NEW_TYPE.append('2') NEW_TYPE = set(NEW_TYPE) #if old and new position is different refresh both. for v in (TYPE | NEW_TYPE): fresh_old = CMSFresh(v) fresh_old.start() else: super(Message, self).write(cr, uid, ids, vals, context=context) return True def unlink(self, cr, uid, ids, context=None): #get old position TYPE = [] messages_old = self.pool.get('message.message').browse(cr, 1, ids, context=context) for message_old in messages_old: if message_old.category_id.display_position == 'shortcut': TYPE.append('0') if message_old.category_id.display_position == 'content_left': TYPE.append('1') if message_old.category_id.display_position == 'content_right': TYPE.append('2') super(Message, self).unlink(cr, uid, ids, context=None) TYPE = set(TYPE) #refresh for v in TYPE: fresh_old = CMSFresh(v) fresh_old.start() return True def vote_like(self, cr, uid, user_id, message_id, context=None): message_vote_obj = self.pool.get('message.vote') message = self.read(cr, SUPERUSER_ID, int(message_id), ['vote_user_ids'], context=context) new_has_voted = not (user_id in message.get('vote_user_ids')) if new_has_voted: message_vote_obj.create(cr, SUPERUSER_ID, {'message_id': message.get('id'), 'user_id': user_id, 'up': True}) else: self.write(cr, SUPERUSER_ID, [message.get('id')], {'vote_user_ids': [(3, user_id)]}, context=context) message_vote_obj.create(cr, SUPERUSER_ID, {'message_id': message.get('id'), 'user_id': user_id, 'up': True}) return new_has_voted or False def vote_unlike(self, cr, uid, user_id, message_id, context=None): message_vote_obj = self.pool.get('message.vote') message = self.read(cr, SUPERUSER_ID, int(message_id), ['vote_user_ids'], context=context) new_has_voted = not (user_id in message.get('vote_user_ids')) if new_has_voted: message_vote_obj.create(cr, SUPERUSER_ID, {'message_id': message.get('id'), 'user_id': user_id, 'up': False}) else: self.write(cr, SUPERUSER_ID, [message.get('id')], {'vote_user_ids': [(3, user_id)]}, context=context) message_vote_obj.create(cr, SUPERUSER_ID, {'message_id': message.get('id'), 'user_id': user_id, 'up': False}) return new_has_voted or False
class nh_clinical_activity_access(orm.Model): """ Adds an additional permission type called ``perm_responsibility`` to an activity. This defines if a particular user group can or cannot perform an activity. """ _name = 'nh.clinical.activity.access' _auto = False _columns = { 'user_id': fields.many2one('res.users', 'User'), 'location_ids_text': fields.text('Location IDS Text'), 'parent_location_ids_text': fields.text('Parent Location IDS Text'), 'location_activity_ids_text': fields.text('Activity IDS Text'), 'parent_location_activity_ids_text': fields.text('Parent Location Activity IDS Text'), } def init(self, cr): cr.execute(""" drop view if exists nh_clinical_activity_access; create or replace view nh_clinical_activity_access as( with recursive route(level, path, parent_id, id) as ( select 0, id::text, parent_id, id from nh_clinical_location where parent_id is null union select level + 1, path||','||location.id, location.parent_id, location.id from nh_clinical_location location join route on location.parent_id = route.id ), location_parents as ( select id as location_id, ('{'||path||'}')::int[] as ids from route order by path ), user_access as ( select u.id as user_id, array_agg(access.model_id) as model_ids from res_users u inner join res_groups_users_rel gur on u.id = gur.uid inner join ir_model_access access on access.group_id = gur.gid and access.perm_responsibility = true group by u.id ), user_location as ( select ulr.user_id, array_agg(ulr.location_id) as location_ids from user_location_rel ulr group by ulr.user_id ), user_location_parents_map as ( select distinct user_location.user_id, parent_location_id from user_location inner join location_parents on user_location.location_ids && array[location_parents.location_id] inner join unnest(location_parents.ids) as parent_location_id on array[parent_location_id] && location_parents.ids ), user_location_parents as ( select user_id, array_agg(parent_location_id) as ids from user_location_parents_map group by user_id ), user_activity as ( select user_location.user_id, array_agg(activity.id) as activity_ids from user_location inner join user_access on user_location.user_id = user_access.user_id inner join nh_activity activity on array[activity.location_id] && user_location.location_ids inner join ir_model model on model.model = activity.data_model and array[model.id] && user_access.model_ids group by user_location.user_id ), user_parent_location_activity as( select user_location_parents.user_id, array_agg(activity.id) as ids from user_location_parents inner join nh_activity activity on array[activity.location_id] && user_location_parents.ids group by user_location_parents.user_id ) select user_access.user_id as id, user_access.user_id, user_location.location_ids::text as location_ids_text, user_location_parents.ids::text as parent_location_ids_text, user_activity.activity_ids::text as location_activity_ids_text, user_parent_location_activity.ids::text as parent_location_activity_ids_text, user_location.location_ids as location_ids, user_location_parents.ids as parent_location_ids, user_activity.activity_ids as location_activity_ids, user_parent_location_activity.ids as parent_location_activity_ids from user_access inner join user_location on user_location.user_id = user_access.user_id inner join user_activity on user_activity.user_id = user_access.user_id inner join user_location_parents on user_location_parents.user_id = user_access.user_id inner join user_parent_location_activity on user_parent_location_activity.user_id = user_access.user_id ); """)
class nh_activity(orm.Model): """ Extends class :class:`nh_activity<activity.nh_activity>`. """ _name = 'nh.activity' _inherit = 'nh.activity' _columns = { 'user_ids': fields.many2many('res.users', 'activity_user_rel', 'activity_id', 'user_id', 'Users', readonly=True), 'patient_id': fields.many2one('nh.clinical.patient', 'Patient', readonly=True), 'location_id': fields.many2one('nh.clinical.location', 'Location', readonly=True), 'location_name': fields.related('location_id', 'full_name', type='char', size=150, string='Location Name'), 'pos_id': fields.many2one('nh.clinical.pos', 'POS', readonly=True), 'spell_activity_id': fields.many2one('nh.activity', 'Spell Activity', readonly=True), 'cancel_reason_id': fields.many2one('nh.cancel.reason', 'Cancellation Reason'), 'ward_manager_id': fields.many2one('res.users', 'Ward Manager of the ward on Complete/Cancel') } def create(self, cr, uid, vals, context=None): """ Extends Odoo's `create()` method. Writes ``user_ids`` for responsible users of the activities` location. :param vals: values to create record :type vals: doct :returns: :class:`nh_activity<activity.nh_activity>` id :rtype: int """ res = super(nh_activity, self).create(cr, uid, vals, context=context) if vals.get('location_id'): user_ids = self.pool['nh.activity.data'].get_activity_user_ids( cr, uid, res, context=context) if vals.get('data_model') == 'nh.clinical.spell': self.update_users(cr, uid, user_ids) else: self.write(cr, uid, res, {'user_ids': [[6, False, user_ids]]}) return res def write(self, cr, uid, ids, values, context=None): """ Extends Odoo's `write()` method. Also writes ``user_ids`` for responsible users of the activities' location. See class :mod:`nh_clinical_location<base.nh_clinical_location>`. :param ids: :class:`nh_activity<activity.nh_activity>` record ids :type ids: list :param vals: values to update records (may include ``location_id``) :type vals: dict :returns: ``True`` :rtype: bool """ if not values: values = {} res = super(nh_activity, self).write(cr, uid, ids, values, context=context) if 'location_id' in values: location_pool = self.pool['nh.clinical.location'] location = location_pool.read(cr, uid, values['location_id'], ['user_ids'], context=context) if location: self.write(cr, uid, ids, {'user_ids': [[6, False, location['user_ids']]]}, context=context) return res def cancel_open_activities(self, cr, uid, parent_id, model, context=None): """ Cancels all open activities of parent activity. :param parent_id: id of the parent activity :type parent_id: int :param model: model (type) of activity :type model: str :returns: ``True`` if all open activities are cancelled or if there are no open activities. Otherwise, ``False`` :rtype: bool """ domain = [('parent_id', '=', parent_id), ('data_model', '=', model), ('state', 'not in', ['completed', 'cancelled'])] open_activity_ids = self.search(cr, uid, domain, context=context) return all([ self.cancel(cr, uid, a, context=context) for a in open_activity_ids ]) def update_users(self, cr, uid, user_ids): """ Updates activities with the user_ids of users responsible for the activities' locations. :param user_ids: user ids. See class :class:`res_users<base.res_users>` :type user_ids: list :returns: ``True`` :rtype: bool """ if not user_ids: return True where_clause = "where user_id in (%s)" % list2sqlstr(user_ids) sql = """ delete from activity_user_rel {where_clause}; insert into activity_user_rel select activity_id, user_id from (select distinct on (activity.id, ulr.user_id) activity.id as activity_id, ulr.user_id from user_location_rel ulr inner join res_groups_users_rel gur on ulr.user_id = gur.uid inner join ir_model_access access on access.group_id = gur.gid and access.perm_responsibility = true inner join ir_model model on model.id = access.model_id inner join nh_activity activity on model.model = activity.data_model and activity.location_id = ulr.location_id and activity.state not in ('completed','cancelled') where not exists (select 1 from activity_user_rel where activity_id=activity.id and user_id=ulr.user_id )) pairs {where_clause} """.format(where_clause=where_clause) cr.execute(sql) self.update_spell_users(cr, uid, user_ids) return True def update_spell_users(self, cr, uid, user_ids=None): """ Updates spell activities with the user_ids of users responsible for parent locations of spell location. :param user_ids: user ids. See class :class:`res_users<base.res_users>` :type user_ids: list :returns: ``True`` :rtype: bool """ if not user_ids: return True where_clause = "where user_id in (%s)" % list2sqlstr(user_ids) sql = """ with recursive route(level, path, parent_id, id) as ( select 0, id::text, parent_id, id from nh_clinical_location where parent_id is null union select level + 1, path||','||location.id, location.parent_id, location.id from nh_clinical_location location join route on location.parent_id = route.id ), parent_location as ( select id as location_id, ('{'||path||'}')::int[] as ids from route order by path ) insert into activity_user_rel select activity_id, user_id from ( select distinct on (activity.id, ulr.user_id) activity.id as activity_id, ulr.user_id from user_location_rel ulr inner join res_groups_users_rel gur on ulr.user_id = gur.uid inner join ir_model_access access on access.group_id = gur.gid and access.perm_responsibility = true inner join ir_model model on model.id = access.model_id and model.model = 'nh.clinical.spell' inner join parent_location on parent_location.ids && array[ulr.location_id] inner join nh_activity activity on model.model = activity.data_model and activity.location_id = parent_location.location_id where not exists (select 1 from activity_user_rel where activity_id=activity.id and user_id=ulr.user_id )) pairs %s """ % where_clause cr.execute(sql) return True
def _setup_bound_dimension(cls, dimension, columns, defaults, orm_name, name, bases, nmspc): """Bind a dimension to the model, creating a code for each record.""" if dimension is True: dimension = {} elif isinstance(dimension, basestring): dimension = {"name": dimension} dimension_name = dimension.get("name", None) if dimension_name is None: dimension_name = nmspc.get("_description", False) or orm_name column = dimension.get("column", "analytic_id") ref_module = dimension.get("ref_module", "") ref_id = dimension.get("ref_id", None) if ref_id is None: ref_id = orm_name.replace(".", "_") + "_analytic_dimension_id" # To use an inherited, renamed parent field, you have to give its name. sync_parent = dimension.get("sync_parent", False) if sync_parent is True: sync_parent = nmspc.get("_parent_name", "parent_id") rel_name = dimension.get("rel_name", tuple()) if rel_name is True: rel_name = u"Name" if isinstance(rel_name, basestring): rel_name = (rel_name, "name") rel_description = dimension.get("rel_description", tuple()) if rel_description is True: rel_description = u"Description" if isinstance(rel_description, basestring): rel_description = (rel_description, "description") rel_active = dimension.get("rel_active", tuple()) if rel_active is True: rel_active = u"Active" if isinstance(rel_active, basestring): rel_active = (rel_active, "active") rel_view_type = dimension.get("rel_view_type", tuple()) if rel_view_type is True: rel_view_type = u"View type" if isinstance(rel_view_type, basestring): rel_view_type = (rel_view_type, "view_type") rel_disabled_per_company = dimension.get("rel_disabled_per_company", tuple()) if rel_disabled_per_company is True: rel_disabled_per_company = u"Disabled in my company" if isinstance(rel_disabled_per_company, basestring): rel_disabled_per_company = (rel_disabled_per_company, "disabled_per_company") # By default, only use inherits if we can be sure there is no conflict # on the required fields 'name' and 'nd_id'. # There can still be conflicts on analytic_code's optional fields. use_inherits = dimension.get("use_inherits", None) if use_inherits is None: use_inherits = not ( any(col in columns for col in ("name", "nd_id")) or nmspc.get("_inherits", False) or nmspc.get("_inherit", False) ) use_code_name_methods = dimension.get("use_code_name_methods", False) code_ref_ids = dimension.get("code_ref_ids", False) if code_ref_ids is True: code_ref_ids = ref_id code_ref_module = dimension.get("code_ref_module", "") if use_inherits: inherits = nmspc.get("_inherits", {}) inherits["analytic.code"] = column nmspc["_inherits"] = inherits # Default column for the underlying analytic code. if column not in columns: columns[column] = fields.many2one( "analytic.code", u"Bound Analytic Code", required=True, ondelete="restrict" ) rel_cols = [ cols for cols in [ rel_name + ("name", "char", True, ""), rel_description + ("description", "char", False, ""), rel_active + ("active", "boolean", False, True), rel_view_type + ("view_type", "boolean", False, False), ] if len(cols) == 6 ] if rel_cols: # NOT a method nor a class member. 'self' is the analytic_code OSV. def _record_from_code_id(self, cr, uid, ids, context=None): """Get the entries to update from the modified codes.""" osv = self.pool.get(orm_name) domain = [(column, "in", ids)] return osv.search(cr, uid, domain, context=context) for string, model_col, code_col, dtype, req, default in rel_cols: columns[model_col] = fields.related( column, code_col, string=string, type=dtype, relation="analytic.code", required=req, store={"analytic.code": (_record_from_code_id, [code_col], 10)}, ) if model_col not in defaults: defaults[model_col] = default # In order to preserve inheritance, possible overrides, and OEMetaSL's # expected behavior, work on a new class that inherits the given bases, # then make our model class inherit from this class. superclass_name = "_{name}_SuperDimension".format(name=name) # Set _register to False in order to prevent its instantiation. superclass = type(superclass_name, bases, {"_register": False}) @AddMethod(superclass) def __init__(self, pool, cr): """Load or create the analytic dimension bound to the model.""" super(superclass, self).__init__(pool, cr) data_osv = self.pool["ir.model.data"] try: self._bound_dimension_id = data_osv.get_object_reference(cr, SUPERUSER_ID, ref_module, ref_id)[1] except ValueError: vals = {"name": dimension_name, "validated": True} self._bound_dimension_id = data_osv._update( cr, SUPERUSER_ID, "analytic.dimension", ref_module, vals, xml_id=ref_id, noupdate=True ) if code_ref_ids: prefix = config.get_misc("analytic", "code_ref_prefix", False) # This function is called as a method and can be overridden. @AddMethod(superclass) def _generate_code_ref_id(self, cr, uid, ids, context=None): data_osv = self.pool["ir.model.data"] records = self.browse(cr, uid, ids, context=None) if not isinstance(records, list): records = [records] for record in records: code = record[column] code_ref_id_builder = [prefix] if prefix else [] if "company_id" in record and record.company_id: code_ref_id_builder.append(record.company_id.code) code_ref_id_builder.append("ANC") code_ref_id_builder.append(code_ref_ids) code_ref_id_builder.append(code.name) vals = { "name": "_".join(code_ref_id_builder), "module": code_ref_module, "model": "analytic.code", "res_id": code.id, } data_osv.create(cr, uid, vals, context=context) @AddMethod(superclass) def create(self, cr, uid, vals, context=None): """Create the analytic code.""" code_vals = {} if sync_parent: cp = self._get_code_parent(cr, uid, vals, context=context) if cp is not None: code_vals["code_parent_id"] = cp # Direct changes to the 'bound analytic code' field are ignored # unless the 'force_code_id' context key is passed as True. force_code_id = vals.pop(column, False) if context and context.get("force_code_id", False) == True: self._force_code(cr, uid, force_code_id, code_vals, context) vals[column] = force_code_id else: if use_inherits: code_vals.update(vals) else: code_vals["name"] = vals.get("name") # OpenERP bug: related fields do not work properly on creation. for rel in rel_cols: model_col, code_col = rel[1:3] if model_col in vals: code_vals[code_col] = vals[model_col] elif model_col in self._defaults: code_vals[code_col] = self._defaults[model_col] # We have to create the code separately, even with inherits. code_osv = self.pool["analytic.code"] code_vals["nd_id"] = self._bound_dimension_id code_id = code_osv.create(cr, uid, code_vals, context=context) vals[column] = code_id res = super(superclass, self).create(cr, uid, vals, context=context) if code_ref_ids: self._generate_code_ref_id(cr, uid, res, context=context) return res @AddMethod(superclass) def write(self, cr, uid, ids, vals, context=None): """Update the analytic code's name if it is not inherited, and its parent code if parent-child relations are synchronized. """ code_vals = {} new = False if not isinstance(ids, (list, tuple)): ids = [ids] if sync_parent: cp = self._get_code_parent(cr, uid, vals, context=context) if cp is not None: code_vals["code_parent_id"] = cp # Direct changes to the 'bound analytic code' field are ignored # unless the 'force_code_id' context key is passed as True. force_code_id = vals.pop(column, False) if context and context.get("force_code_id", False) == True: self._force_code(cr, uid, force_code_id, code_vals, context) vals[column] = force_code_id elif use_inherits: vals.update(code_vals) else: name_col = rel_name[1] if rel_name else "name" if name_col in vals: code_vals["name"] = vals[name_col] records = self.browse(cr, uid, ids, context=context) code_ids = [getattr(rec, column).id for rec in records] # If updating a single record with no code, create it. code_osv = self.pool["analytic.code"] if code_ids == [False]: new = ids[0] code_vals["nd_id"] = self._bound_dimension_id if "name" not in code_vals: code_vals["name"] = self.read(cr, uid, new, [name_col], context=context)[name_col] vals[column] = code_osv.create(cr, uid, code_vals, context=context) elif code_vals: code_osv.write(cr, uid, code_ids, code_vals, context=context) res = super(superclass, self).write(cr, uid, ids, vals, context=context) if code_ref_ids and new is not False: self._generate_code_ref_id(cr, uid, new, context=context) return res @AddMethod(superclass) def _force_code(self, cr, uid, force_code_id, code_vals, context=None): code_osv = self.pool["analytic.code"] if not force_code_id: raise ValueError( "An analytic code ID MUST be specified if the " "force_code_id key is enabled in the context" ) force_code_dim = code_osv.read(cr, uid, force_code_id, ["nd_id"], context=context)["nd_id"][0] if force_code_dim != self._bound_dimension_id: raise ValueError( "If specified, codes must belong to the bound " "analytic dimension {}".format(dimension_name) ) if code_vals: code_osv.write(cr, uid, force_code_id, code_vals, context=context) if sync_parent: # This function is called as a method and can be overridden. @AddMethod(superclass) def _get_code_parent(self, cr, uid, vals, context=None): """If parent_id is in the submitted values, return the analytic code of this parent, to be used as the child's code's parent. """ parent_id = vals.get(sync_parent, None) if parent_id is not None: if parent_id: res = self.read(cr, uid, parent_id, [column], context=context)[column] return res[0] if res else False else: return False return None if use_code_name_methods: @AddMethod(superclass) def name_get(self, cr, uid, ids, context=None): """Return the analytic code's name.""" code_osv = self.pool.get("analytic.code") code_reads = self.read(cr, uid, ids, [column], context=context) c2m = { # Code IDs to model IDs code_read[column][0]: code_read["id"] for code_read in code_reads if code_read[column] is not False } names = code_osv.name_get(cr, uid, c2m.keys(), context=context) return [(c2m[cid], name) for cid, name in names if cid in c2m] @AddMethod(superclass) def name_search(self, cr, uid, name, args=None, operator="ilike", context=None, limit=100): """Return the records whose analytic code matches the name.""" code_osv = self.pool.get("analytic.code") args.append(("nd_id", "=", self._bound_dimension_id)) names = code_osv.name_search(cr, uid, name, args, operator, context, limit) if not names: return [] dom = [(column, "in", zip(*names)[0])] ids = self.search(cr, uid, dom, context=context) code_reads = self.read(cr, uid, ids, [column], context=context) c2m = { # Code IDs to model IDs code_read[column][0]: code_read["id"] for code_read in code_reads if code_read[column] is not False } return [(c2m[cid], cname) for cid, cname in names if cid in c2m] return (superclass,)
class procurement_order(osv.osv): _inherit = "procurement.order" _columns = { 'location_id': fields.many2one( 'stock.location', 'Procurement Location' ), # not required because task may create procurements that aren't linked to a location with sale_service 'partner_dest_id': fields.many2one( 'res.partner', 'Customer Address', help= "In case of dropshipping, we need to know the destination address more precisely" ), 'move_ids': fields.one2many('stock.move', 'procurement_id', 'Moves', help="Moves created by the procurement"), 'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Move which caused (created) the procurement"), 'route_ids': fields.many2many( 'stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Preferred Routes', help= "Preferred route to be followed by the procurement order. Usually copied from the generating document (SO) but could be set up manually." ), 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', help="Warehouse to consider for the route selection"), 'orderpoint_id': fields.many2one('stock.warehouse.orderpoint', 'Minimum Stock Rule'), } def propagate_cancel(self, cr, uid, procurement, context=None): if procurement.rule_id.action == 'move' and procurement.move_ids: self.pool.get('stock.move').action_cancel( cr, uid, [m.id for m in procurement.move_ids], context=context) def cancel(self, cr, uid, ids, context=None): if context is None: context = {} to_cancel_ids = self.get_cancel_ids(cr, uid, ids, context=context) ctx = context.copy() #set the context for the propagation of the procurement cancelation ctx['cancel_procurement'] = True for procurement in self.browse(cr, uid, to_cancel_ids, context=ctx): self.propagate_cancel(cr, uid, procurement, context=ctx) return super(procurement_order, self).cancel(cr, uid, to_cancel_ids, context=ctx) def _find_parent_locations(self, cr, uid, procurement, context=None): location = procurement.location_id res = [location.id] while location.location_id: location = location.location_id res.append(location.id) return res def change_warehouse_id(self, cr, uid, ids, warehouse_id, context=None): if warehouse_id: warehouse = self.pool.get('stock.warehouse').browse( cr, uid, warehouse_id, context=context) return {'value': {'location_id': warehouse.lot_stock_id.id}} return {} def _search_suitable_rule(self, cr, uid, procurement, domain, context=None): '''we try to first find a rule among the ones defined on the procurement order group and if none is found, we try on the routes defined for the product, and finally we fallback on the default behavior''' pull_obj = self.pool.get('procurement.rule') warehouse_route_ids = [] if procurement.warehouse_id: domain += [ '|', ('warehouse_id', '=', procurement.warehouse_id.id), ('warehouse_id', '=', False) ] warehouse_route_ids = [ x.id for x in procurement.warehouse_id.route_ids ] product_route_ids = [ x.id for x in procurement.product_id.route_ids + procurement.product_id.categ_id.total_route_ids ] procurement_route_ids = [x.id for x in procurement.route_ids] res = pull_obj.search(cr, uid, domain + [('route_id', 'in', procurement_route_ids)], order='route_sequence, sequence', context=context) if not res: res = pull_obj.search(cr, uid, domain + [('route_id', 'in', product_route_ids)], order='route_sequence, sequence', context=context) if not res: res = warehouse_route_ids and pull_obj.search( cr, uid, domain + [('route_id', 'in', warehouse_route_ids)], order='route_sequence, sequence', context=context) or [] if not res: res = pull_obj.search(cr, uid, domain + [('route_id', '=', False)], order='sequence', context=context) return res def _find_suitable_rule(self, cr, uid, procurement, context=None): rule_id = super(procurement_order, self)._find_suitable_rule(cr, uid, procurement, context=context) if not rule_id: #a rule defined on 'Stock' is suitable for a procurement in 'Stock\Bin A' all_parent_location_ids = self._find_parent_locations( cr, uid, procurement, context=context) rule_id = self._search_suitable_rule( cr, uid, procurement, [('location_id', 'in', all_parent_location_ids)], context=context) rule_id = rule_id and rule_id[0] or False return rule_id def _run_move_create(self, cr, uid, procurement, context=None): ''' Returns a dictionary of values that will be used to create a stock move from a procurement. This function assumes that the given procurement has a rule (action == 'move') set on it. :param procurement: browse record :rtype: dictionary ''' newdate = ( datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.rule_id.delay or 0) ).strftime('%Y-%m-%d %H:%M:%S') group_id = False if procurement.rule_id.group_propagation_option == 'propagate': group_id = procurement.group_id and procurement.group_id.id or False elif procurement.rule_id.group_propagation_option == 'fixed': group_id = procurement.rule_id.group_id and procurement.rule_id.group_id.id or False #it is possible that we've already got some move done, so check for the done qty and create #a new move with the correct qty already_done_qty = 0 already_done_qty_uos = 0 for move in procurement.move_ids: already_done_qty += move.product_uom_qty if move.state == 'done' else 0 already_done_qty_uos += move.product_uos_qty if move.state == 'done' else 0 qty_left = max(procurement.product_qty - already_done_qty, 0) qty_uos_left = max(procurement.product_uos_qty - already_done_qty_uos, 0) vals = { 'name': procurement.name, 'company_id': procurement.rule_id.company_id.id or procurement.rule_id.location_src_id.company_id.id or procurement.rule_id.location_id.company_id.id or procurement.company_id.id, 'product_id': procurement.product_id.id, 'product_uom': procurement.product_uom.id, 'product_uom_qty': qty_left, 'product_uos_qty': (procurement.product_uos and qty_uos_left) or qty_left, 'product_uos': (procurement.product_uos and procurement.product_uos.id) or procurement.product_uom.id, 'partner_id': procurement.rule_id.partner_address_id.id or (procurement.group_id and procurement.group_id.partner_id.id) or False, 'location_id': procurement.rule_id.location_src_id.id, 'location_dest_id': procurement.location_id.id, 'move_dest_id': procurement.move_dest_id and procurement.move_dest_id.id or False, 'procurement_id': procurement.id, 'rule_id': procurement.rule_id.id, 'procure_method': procurement.rule_id.procure_method, 'origin': procurement.origin, 'picking_type_id': procurement.rule_id.picking_type_id.id, 'group_id': group_id, 'route_ids': [(4, x.id) for x in procurement.route_ids], 'warehouse_id': procurement.rule_id.propagate_warehouse_id.id or procurement.rule_id.warehouse_id.id, 'date': newdate, 'date_expected': newdate, 'propagate': procurement.rule_id.propagate, 'priority': procurement.priority, } return vals def _run(self, cr, uid, procurement, context=None): if procurement.rule_id and procurement.rule_id.action == 'move': if not procurement.rule_id.location_src_id: self.message_post(cr, uid, [procurement.id], body=_('No source location defined!'), context=context) return False move_obj = self.pool.get('stock.move') move_dict = self._run_move_create(cr, uid, procurement, context=context) #create the move as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) move_obj.create(cr, SUPERUSER_ID, move_dict, context=context) return True return super(procurement_order, self)._run(cr, uid, procurement, context=context) def run(self, cr, uid, ids, autocommit=False, context=None): new_ids = [ x.id for x in self.browse(cr, uid, ids, context=context) if x.state not in ('running', 'done', 'cancel') ] res = super(procurement_order, self).run(cr, uid, new_ids, autocommit=autocommit, context=context) #after all the procurements are run, check if some created a draft stock move that needs to be confirmed #(we do that in batch because it fasts the picking assignation and the picking state computation) move_to_confirm_ids = [] for procurement in self.browse(cr, uid, new_ids, context=context): if procurement.state == "running" and procurement.rule_id and procurement.rule_id.action == "move": move_to_confirm_ids += [ m.id for m in procurement.move_ids if m.state == 'draft' ] if move_to_confirm_ids: self.pool.get('stock.move').action_confirm(cr, uid, move_to_confirm_ids, context=context) return res def _check(self, cr, uid, procurement, context=None): ''' Implement the procurement checking for rules of type 'move'. The procurement will be satisfied only if all related moves are done/cancel and if the requested quantity is moved. ''' if procurement.rule_id and procurement.rule_id.action == 'move': uom_obj = self.pool.get('product.uom') # In case Phantom BoM splits only into procurements if not procurement.move_ids: return True cancel_test_list = [ x.state == 'cancel' for x in procurement.move_ids ] done_cancel_test_list = [ x.state in ('done', 'cancel') for x in procurement.move_ids ] at_least_one_cancel = any(cancel_test_list) all_done_or_cancel = all(done_cancel_test_list) all_cancel = all(cancel_test_list) if not all_done_or_cancel: return False elif all_done_or_cancel and not all_cancel: return True elif all_cancel: self.message_post( cr, uid, [procurement.id], body= _('All stock moves have been cancelled for this procurement.' ), context=context) self.write(cr, uid, [procurement.id], {'state': 'cancel'}, context=context) return False return super(procurement_order, self)._check(cr, uid, procurement, context) def do_view_pickings(self, cr, uid, ids, context=None): ''' This function returns an action that display the pickings of the procurements belonging to the same procurement group of given ids. ''' mod_obj = self.pool.get('ir.model.data') act_obj = self.pool.get('ir.actions.act_window') result = mod_obj.get_object_reference(cr, uid, 'stock', 'do_view_pickings') id = result and result[1] or False result = act_obj.read(cr, uid, [id], context=context)[0] group_ids = set([ proc.group_id.id for proc in self.browse(cr, uid, ids, context=context) if proc.group_id ]) result['domain'] = "[('group_id','in',[" + ','.join( map(str, list(group_ids))) + "])]" return result def run_scheduler(self, cr, uid, use_new_cursor=False, company_id=False, context=None): ''' Call the scheduler in order to check the running procurements (super method), to check the minimum stock rules and the availability of moves. This function is intended to be run for all the companies at the same time, so we run functions as SUPERUSER to avoid intercompanies and access rights issues. @param self: The object pointer @param cr: The current row, from the database cursor, @param uid: The current user ID for security checks @param ids: List of selected IDs @param use_new_cursor: if set, use a dedicated cursor and auto-commit after processing each procurement. This is appropriate for batch jobs only. @param context: A standard dictionary for contextual values @return: Dictionary of values ''' super(procurement_order, self).run_scheduler(cr, uid, use_new_cursor=use_new_cursor, company_id=company_id, context=context) if context is None: context = {} try: if use_new_cursor: cr = openerp.registry(cr.dbname).cursor() move_obj = self.pool.get('stock.move') #Minimum stock rules self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=use_new_cursor, company_id=company_id, context=context) #Search all confirmed stock_moves and try to assign them confirmed_ids = move_obj.search( cr, uid, [('state', '=', 'confirmed')], limit=None, order='priority desc, date_expected asc', context=context) for x in xrange(0, len(confirmed_ids), 100): move_obj.action_assign(cr, uid, confirmed_ids[x:x + 100], context=context) if use_new_cursor: cr.commit() if use_new_cursor: cr.commit() finally: if use_new_cursor: try: cr.close() except Exception: pass return {} def _get_orderpoint_date_planned(self, cr, uid, orderpoint, start_date, context=None): date_planned = start_date + relativedelta( days=orderpoint.product_id.seller_delay or 0.0) return date_planned.strftime(DEFAULT_SERVER_DATE_FORMAT) def _prepare_orderpoint_procurement(self, cr, uid, orderpoint, product_qty, context=None): return { 'name': orderpoint.name, 'date_planned': self._get_orderpoint_date_planned(cr, uid, orderpoint, datetime.today(), context=context), 'product_id': orderpoint.product_id.id, 'product_qty': product_qty, 'company_id': orderpoint.company_id.id, 'product_uom': orderpoint.product_uom.id, 'location_id': orderpoint.location_id.id, 'origin': orderpoint.name, 'warehouse_id': orderpoint.warehouse_id.id, 'orderpoint_id': orderpoint.id, 'group_id': orderpoint.group_id.id, } def _product_virtual_get(self, cr, uid, order_point): product_obj = self.pool.get('product.product') return product_obj._product_available( cr, uid, [order_point.product_id.id], context={'location': order_point.location_id.id })[order_point.product_id.id]['virtual_available'] def _procure_orderpoint_confirm(self, cr, uid, use_new_cursor=False, company_id=False, context=None): ''' Create procurement based on Orderpoint :param bool use_new_cursor: if set, use dedicated cursors and auto-commit after processing 100 orderpoints. This is appropriate for batch jobs only. ''' if context is None: context = {} orderpoint_obj = self.pool.get('stock.warehouse.orderpoint') procurement_obj = self.pool.get('procurement.order') dom = company_id and [('company_id', '=', company_id)] or [] orderpoint_ids = orderpoint_obj.search(cr, uid, dom, context=context) prev_ids = [] while orderpoint_ids: ids = orderpoint_ids[:100] del orderpoint_ids[:100] if use_new_cursor: cr = openerp.registry(cr.dbname).cursor() for op in orderpoint_obj.browse(cr, uid, ids, context=context): try: prods = self._product_virtual_get(cr, uid, op) if prods is None: continue if float_compare( prods, op.product_min_qty, precision_rounding=op.product_uom.rounding) < 0: qty = max(op.product_min_qty, op.product_max_qty) - prods reste = op.qty_multiple > 0 and qty % op.qty_multiple or 0.0 if float_compare(reste, 0.0, precision_rounding=op.product_uom. rounding) > 0: qty += op.qty_multiple - reste if float_compare(qty, 0.0, precision_rounding=op.product_uom. rounding) <= 0: continue qty -= orderpoint_obj.subtract_procurements( cr, uid, op, context=context) qty_rounded = float_round( qty, precision_rounding=op.product_uom.rounding) if qty_rounded > 0: proc_id = procurement_obj.create( cr, uid, self._prepare_orderpoint_procurement( cr, uid, op, qty_rounded, context=context), context=context) self.check(cr, uid, [proc_id], context=context) self.run(cr, uid, [proc_id], context=context) if use_new_cursor: cr.commit() except OperationalError: if use_new_cursor: orderpoint_ids.append(op.id) cr.rollback() continue else: raise if use_new_cursor: cr.commit() cr.close() if prev_ids == ids: break else: prev_ids = ids return {}
def _method_get(self, cr, uid, context=None): res = super(sale_order, self)._method_get(cr, uid, context=context) res.append(('ups.account', 'UPS')) return res _columns = { 'payment_method':fields.selection([ ('cc_pre_auth', 'Credit Card – PreAuthorized'), ('invoice', 'Invoice'), ('cod', 'COD'), ('p_i_a', 'Pay In Advance'), ('pay_pal', 'Paypal'), ('no_charge', 'No Charge')], 'Payment Method'), 'ship_company_code': fields.selection(_get_company_code, 'Logistic Company', method=True, size=64), <<<<<<< HEAD 'ups_shipper_id': fields.many2one('ups.account.shipping', 'Shipping Account'), ======= 'ups_shipper_id': fields.many2one('ups.account.shipping', 'Shipper'), >>>>>>> c1979f64b3360c86d60e00c92be0271d89f97f2d 'ups_service_id': fields.many2one('ups.shipping.service.type', 'Service Type'), 'ups_pickup_type': fields.selection([ ('01', 'Daily Pickup'), ('03', 'Customer Counter'), ('06', 'One Time Pickup'), ('07', 'On Call Air'), ('11', 'Suggested Retail Rates'), ('19', 'Letter Center'), ('20', 'Air Service Center'), ], 'Pickup Type'), 'ups_packaging_type': fields.many2one('shipping.package.type', 'Packaging Type'), 'shipping_rates': fields.one2many('shipping.rates.sales', 'sales_id', 'Rate Quotes'),
class procurement_group(osv.osv): _inherit = 'procurement.group' _columns = {'partner_id': fields.many2one('res.partner', 'Partner')}
- The 'Invoice From The Picking' choice is used to create an invoice during the picking process."""), 'state': fields.selection([ ('draft', 'Draft Quotation'), ('sent', 'Quotation Sent'), ('cancel', 'Cancelled'), ('waiting_date', 'Waiting Schedule'), ('progress', 'Sales Order'), ('cc_auth', 'Draft Authorized'), ('manual', 'Sale to Invoice'), ('invoice_except', 'Invoice Exception'), ('shipping_except', 'Shipping Exception'), ('done', 'Done') ], 'Status', readonly=True, track_visibility='onchange', help="Gives the status of the quotation or sales order. \nThe exception status is automatically set when a cancel operation occurs in the processing of a document linked to the sales order. \nThe 'Waiting Schedule' status is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True), 'cc_pre_auth':fields.boolean('Creditcard Pre-authorised'), 'rel_account_voucher_id':fields.many2one('account.voucher', 'Related Payment'), 'invoiced': fields.function(_invoiced, method=True, string='Paid', type='boolean', help="It indicates that an invoice has been paid.", store={ 'account.invoice' : (_get_invoice, ['state'], 20), 'sale.order' : (lambda self, cr, uid, ids, c={}: ids, ['state'], 20), 'account.voucher' : (_get_voucher, ['state'], 20), }), 'cc_ship_refund' : fields.boolean('Ship Refunded', readonly=True), } def copy(self, cr, uid, id, default=None, context=None): if default is None: default = {} if context is None: context = {}
class procurement_rule(osv.osv): _inherit = 'procurement.rule' def _get_action(self, cr, uid, context=None): result = super(procurement_rule, self)._get_action(cr, uid, context=context) return result + [('move', _('Move From Another Location'))] def _get_rules(self, cr, uid, ids, context=None): res = [] for route in self.browse(cr, uid, ids): res += [x.id for x in route.pull_ids] return res _columns = { 'location_id': fields.many2one('stock.location', 'Procurement Location'), 'location_src_id': fields.many2one('stock.location', 'Source Location', help="Source location is action=move"), 'route_id': fields.many2one('stock.location.route', 'Route', help="If route_id is False, the rule is global"), 'procure_method': fields.selection( [('make_to_stock', 'Take From Stock'), ('make_to_order', 'Create Procurement')], 'Move Supply Method', required=True, help= """Determines the procurement method of the stock move that will be generated: whether it will need to 'take from the available stock' in its source location or needs to ignore its stock and create a procurement over there.""" ), 'route_sequence': fields.related('route_id', 'sequence', string='Route Sequence', store={ 'stock.location.route': (_get_rules, ['sequence'], 10), 'procurement.rule': (lambda self, cr, uid, ids, c={}: ids, ['route_id'], 10), }), 'picking_type_id': fields.many2one( 'stock.picking.type', 'Picking Type', help= "Picking Type determines the way the picking should be shown in the view, reports, ..." ), 'delay': fields.integer('Number of Days'), 'partner_address_id': fields.many2one('res.partner', 'Partner Address'), 'propagate': fields.boolean( 'Propagate cancel and split', help= 'If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too' ), 'warehouse_id': fields.many2one('stock.warehouse', 'Served Warehouse', help='The warehouse this rule is for'), 'propagate_warehouse_id': fields.many2one( 'stock.warehouse', 'Warehouse to Propagate', help= "The warehouse to propagate on the created move/procurement, which can be different of the warehouse this rule is for (e.g for resupplying rules from another warehouse)" ), } _defaults = { 'procure_method': 'make_to_stock', 'propagate': True, 'delay': 0, }
#(at your option) any later version. # # # #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 Affero General Public License for more details. # # # #You should have received a copy of the GNU Affero General Public License # #along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################### from openerp.osv import orm, fields FISCAL_POSITION_COLUMNS = { 'name': fields.char('Fiscal Position', size=128, required=True), 'fiscal_category_id': fields.many2one( 'l10n_br_account.fiscal.category', 'Categoria Fiscal'), 'fiscal_category_fiscal_type': fields.related( 'fiscal_category_id', 'fiscal_type', type='char', readonly=True, relation='l10n_br_account.fiscal.category', store=True, string='Fiscal Type'), 'type': fields.selection([('input', 'Entrada'), ('output', 'Saida')], 'Tipo'), 'type_tax_use': fields.selection( [('sale', 'Sale'), ('purchase', 'Purchase'), ('all', 'All')], 'Tax Application'), 'inv_copy_note': fields.boolean(u'Copiar Observação na Nota Fiscal'), 'asset_operation': fields.boolean(u'Operação de Aquisição de Ativo', help=u"""Caso seja marcada essa opção, será incluido o IPI na base de calculo do ICMS."""), 'state': fields.selection([('draft', u'Rascunho'), ('review', u'Revisão'), ('approved', u'Aprovada'),
class hr_payroll_ma_bulletin_auto(osv.osv): _name = "hr.payroll_ma.bulletin_auto" _inherit = "hr.payroll_ma.bulletin" def get_normal_hours(self, cr, uid, ids, context=None): total_work = self.pool.get('hr.total.work') nh_ids = total_work.search(cr, uid, [('employee_name', '=', self.employee_id), ('period_id', '=', self.period_id)], context=context) nh = total_work.browse(cr, uid, nh_ids, context).normal_working_hours return nh def get_hs_hours(self, cr, uid, ids, context=None): total_work = self.pool.get('hr.total.work') hs_ids = total_work.search(cr, uid, [('employee_name', '=', self.employee_id), ('period_id', '=', self.period_id)], context=context) hs = total_work.browse(cr, uid, hs_ids, context).hs_working_hours return hs def get_working_days(self, cr, uid, ids, context=None): total_work = self.pool.get('hr.total.work') hs_ids = total_work.search(cr, uid, [('employee_name', '=', self.employee_id), ('period_id', '=', self.period_id)], context=context) hs = total_work.browse(cr, uid, hs_ids, context).working_days return hs _columns = { 'employee_id': fields.many2one('hr.employee', 'Employe', change_default=True, readonly=False, required=True, select=1), #'normal_hours' : fields.function(get_normal_hours,type="float"), #'hs_hours' : fields.function(get_hs_hours,type="float"), #'working_days' : fields.function(get_working_days,type="float"), #'normal_hours' : fields.float('heures normales',readonly=True), 'hs_hours': fields.float('heures supplémentaires', readonly=True), #'working_days' : fields.float('jours travaillés',readonly=True), } _defaults = { #'normal_hours': '160', 'hs_hours': '18', 'working_days': '20', }
#the Free Software Foundation, either version 3 of the License, or # #(at your option) any later version. # # # #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 Affero General Public License for more details. # # # #You should have received a copy of the GNU Affero General Public License # #along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################### from openerp.osv import orm, fields FISCAL_POSITION_COLUMNS = { 'cfop_id': fields.many2one('l10n_br_account_product.cfop', 'CFOP'), } class AccountFiscalPositionTemplate(orm.Model): _inherit = 'account.fiscal.position.template' _columns = FISCAL_POSITION_COLUMNS class AccountFiscalPosition(orm.Model): _inherit = 'account.fiscal.position' _columns = FISCAL_POSITION_COLUMNS #TODO - Refatorar para trocar os impostos def map_tax_code(self, cr, uid, product_id, fiscal_position, company_id=False, tax_ids=False, context=None):
class stock_warehouse(osv.osv): _inherit = "stock.warehouse" _columns = { 'delivery_source_loc_id': fields.many2one('stock.location', 'Location Delivery Source (optional)', required=False, domain=[('usage','=','internal')], help="If specified, Delivery Order created from Sales Order will use this as source location"), }
models = [ ('boolean', fields.boolean()), ('integer', fields.integer()), ('float', fields.float()), ('decimal', fields.float(digits=(16, 3))), ('string.bounded', fields.char('unknown', size=16)), ('string.required', fields.char('unknown', size=None, required=True)), ('string', fields.char('unknown', size=None)), ('date', fields.date()), ('datetime', fields.datetime()), ('text', fields.text()), ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux"), (4, '')])), # here use size=-1 to store the values as integers instead of strings ('selection.function', fields.selection(selection_fn, size=-1)), # just relate to an integer ('many2one', fields.many2one('export.integer')), ('one2many', fields.one2many('export.one2many.child', 'parent_id')), ('many2many', fields.many2many('export.many2many.other')), ('function', fields.function(function_fn, fnct_inv=function_fn_write, type="integer")), # related: specialization of fields.function, should work the same way # TODO: reference ] for name, field in models: class NewModel(orm.Model): _name = 'export.%s' % name _columns = { 'const': fields.integer(), 'value': field, } _defaults = {
class stock_partial_picking_line(orm.TransientModel): _inherit = "stock.partial.picking.line" def _get_color_line(self, cr, uid, picking_line, product_ids=[], context=None): if picking_line.product_id.id in product_ids: color = 'blue' elif picking_line.tracking: color = 'red' elif picking_line.line_check or context.get('line_check', False): color = 'grey' else: color = 'black' return color def action_check(self, cr, uid, move_ids, context): line = self.pool['stock.partial.picking.line'].browse(cr, uid, move_ids, context)[0] color = self._get_color_line(cr, uid, line, [], context) line_vals = { 'line_check': not line.line_check, 'row_color': color } line.write(line_vals) return True def action_add(self, cr, uid, move_ids, context): line = self.pool['stock.partial.picking.line'].browse(cr, uid, move_ids, context)[0] dest_qty = line.quantity + 1 if line.move_id.product_qty >= dest_qty: line.write({'quantity': dest_qty}) return True def action_remove(self, cr, uid, move_ids, context): line = self.pool['stock.partial.picking.line'].browse(cr, uid, move_ids, context)[0] if line.quantity >= 1.0: line.write({'quantity': line.quantity - 1}) return True def _get_prodlot_code(self, cr, uid, ids, field_name, arg, context=None): res = {} for move in self.browse(cr, uid, ids): res[move.id] = move.prodlot_id and move.prodlot_id.name or False return res def _set_prodlot_code(self, cr, uid, ids, field_name, value, arg, context=None): if not value: return False if isinstance(ids, (int, long)): ids = [ids] if not hasattr(self, 'serials'): self.serial = {ids[0]: value} else: if not ids[0] in self.serial and value in self.serial.values(): raise orm.except_orm(_('Warning'), (_('Serial number {number} is written more than once').format(number=value))) else: self.serials.append(value) lot_obj = self.pool['stock.production.lot'] for move in self.browse(cr, uid, ids, context=context): product_id = move.product_id.id value = value.upper() existing_prodlot_ids = lot_obj.search(cr, uid, [('name', '=', value), ('product_id', '=', product_id)]) if existing_prodlot_ids and not existing_prodlot_ids[0] == move.prodlot_id.id: raise orm.except_orm(_('Warning'), (_('Serial number "{number}" is already exists').format(number=value))) elif not existing_prodlot_ids: prodlot_id = self.pool['stock.production.lot'].create(cr, uid, { 'name': value, 'product_id': product_id, }) move.write({'prodlot_id': int(prodlot_id)}) return True def get_color(self, cr, uid, ids, field_name, arg, context): res = {} for line in self.browse(cr, uid, ids, context): res[line.id] = 'black' if line.tracking: res[line.id] = 'red' return res def _product_code(self, cr, uid, ids, name, arg, context=None): res = {} if context is None: context = {} product_obj = self.pool['product.product'] for line in self.browse(cr, uid, ids, context=context): partner_id = line.move_id.partner_id and line.move_id.partner_id.id or None code = product_obj._get_partner_code_name(cr, uid, [], line.product_id, partner_id, context=context)['code'] if code != line.product_id.default_code: res[line.id] = code else: res[line.id] = '' return res _columns = { 'code': fields.function(_product_code, type='char', string='Supplier Reference'), 'row_color': fields.char(string='Row color'), 'new_prodlot_code': fields.function(_get_prodlot_code, fnct_inv=_set_prodlot_code, method=True, type='char', size=64, string='Prodlot fast input', select=1 ), 'split_type': fields.related('product_id', 'lot_split_type', type="selection", selection=LOT_SPLIT_TYPE_SELECTION, string="Split", store=False), 'tracking_id': fields.many2one('stock.tracking', 'Pack/Tracking'), 'balance': fields.boolean('Balance'), 'pallet_qty': fields.integer('Number Pallet'), 'pallet_id': fields.many2one('product.ul', 'Pallet', domain=[('type', '=', 'pallet')]), 'line_check': fields.boolean('Check'), } def onchange_new_prodlot_code(self, cr, uid, ids, new_prodlot_code, product_id, prodlot_id, context=None): lot_obj = self.pool['stock.production.lot'] if new_prodlot_code: new_prodlot_code = new_prodlot_code.upper() # all serial number must be on uppercase existing_prodlot_ids = lot_obj.search(cr, uid, [('name', '=', new_prodlot_code), ('product_id', '=', product_id)], limit=1, context=context) existing_lot = lot_obj.browse(cr, uid, existing_prodlot_ids, context) move_type = self.pool['stock.partial.picking.line'].browse(cr, uid, ids, context=context)[0].move_id.picking_id.type if existing_lot: product = self.pool['product.product'].browse(cr, uid, product_id, context=context) if product.lot_split_type == 'single' and move_type != 'out' and existing_lot[0].stock_available > 0: return { 'warning': { 'title': _('Warning!'), 'message': (_('Serial number "{number}" is already exists').format(number=new_prodlot_code)) } } else: existing_lot_id = existing_prodlot_ids[0] return {'value': {'prodlot_id': existing_lot_id}} else: prodlot_id = self.pool['stock.production.lot'].create(cr, uid, { 'name': new_prodlot_code, 'product_id': product_id, }) return {'value': {'prodlot_id': prodlot_id}}
cr.execute("SELECT id, state FROM ir_module_module WHERE name='deferred_processing'") deferred_proc_module = cr.dictfetchone() if deferred_proc_module and deferred_proc_module['state'] in ('installed', 'to upgrade'): result.append('deferred_processing') ############################################ return dict.fromkeys(ids, ','.join(result)) _columns = { 'charset':fields.selection(_get_encodings, string='Charset', required=True), 'content_fname': fields.char('Override Extension',size=64, help='Here you can override output file extension'), 'styles_mode': fields.selection([ ('default','Not used'), ('global', 'Global'), ('specified', 'Specified'), ], string='Stylesheet'), 'stylesheet_id':fields.many2one('report.stylesheets', 'Template Stylesheet'), 'preload_mode':fields.selection([ ('static',_('Static')), ('preload',_('Preload')), ],'Preload Mode'), 'tml_source':fields.selection([ ('database','Database'), ('file','File'), ('parser','Parser'), ],'Template source', select=True), 'parser_def': fields.text('Parser Definition'), 'parser_loc':fields.char('Parser location', size=128, help="Path to the parser location. Beginning of the path must be start with the module name!\nLike this: {module name}/{path to the parser.py file}"), 'parser_state':fields.selection([ ('default',_('Default')), ('def',_('Definition')), ('loc',_('Location')),
class openacademy_session(osv.Model): _name = 'openacademy.session' def _check_instructor_not_in_attendees( self, cr, uid, ids, context=None ): # cuando la fucnion empieza con guion bajo es que es privada, no puedeser usada fuera de open academy if not context: contex = {} print ids, "imprimo ids" for session in self.browse(cr, uid, ids, context): lista_attendee = [] for attendee in session.attendee_ids: lista_attendee.append(attendee.partner_id.id) print lista_attendee, " imprimo lista de attendees" if session.instructor_id and session.instructor_id.id in lista_attendee: return False return True def _get_percent(self, seats, attendee_ids): try: return (100 * len(attendee_ids)) / seats except ZeroDivisionError: return 0.0 def _take_seats_percent(self, cr, uid, ids, field, args, context=None): print field, "field" print args, "args" resultado = {} for session in self.browse(cr, uid, ids, context): resultado[session.id] = self._get_percent(session.seats, session.attendee_ids) print resultado, "resultado" return resultado def onchange_taken_seats(self, cr, uid, ids, seats, attendee_ids): print attendee_ids, "recibe" num_attendees = self.resolve_2many_commands(cr, uid, 'attendee_ids', attendee_ids, ['id']) print num_attendees, "despues" resultado = { 'value': { 'taken_seats_percent': self._get_percent(seats, attendee_ids) } } print resultado if seats < len(num_attendees): resultado['warning'] = { 'title': "Atencion asientos", 'message': "No puedes tener menos asientos que asistentes" } print resultado return resultado def _determin_end_date(self, cr, uid, ids, field, arg, context=None): res = {} for session in self.browse(cr, uid, ids, context): if session.start_date and session.duration: start_date = datetime.strptime(session.start_date, "%Y-%m-%d") duration = timedelta(days=session.duration - 1) end_date = start_date + duration res[session.id] = end_date.strftime("%Y-%m-%d") else: res[session.id] = session.start_date print res return res def _set_end_date(self, cr, uid, id, field, value, arg, context=None): session = self.browse(cr, uid, id, context) if session.start_date and value: start_date = datetime.strptime(session.start_date, "%Y-%m-%d") end_date = datetime.strptime(value, "%Y-%m-%d") duration = end_date - start_date self.write(cr, uid, id, {'duration': duration.days + 1}, context) def _determin_hours_from_duration(self, cr, uid, ids, field, arg, context=None): result = {} sessions = self.browse(cr, uid, ids, context=context) for session in sessions: result[session.id] = (session.duration * 8 if session.duration else 0) return result def _set_hours(self, cr, uid, id, field, value, arg, context=None): if value: self.write(cr, uid, id, {'duration': (value / 8)}, context=context) def _get_attendee_count(self, cr, uid, ids, name, args, context=None): res = {} for session in self.browse(cr, uid, ids, context): res[session.id] = len(session.attendee_ids) return res def action_confirm(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'confirm'}, context=context) def action_draft(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'draft'}, context=context) def action_done(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'done'}, context=context) _columns = { 'name': fields.char(string='Nombre', size=256, required=True), 'start_date': fields.date(string='Fecha Inicio'), 'duration': fields.float(string='Duracion', digits=(6, 2), help='Duracion en dias'), 'seats': fields.integer(string='Numero de asientos'), 'active': fields.boolean(string='Activo'), # 'instructor_id': fields.many2one('res.partner', string='Instructor', domain= ['|',('instructor','=',True),('name','ilike','%axel%')] ), 'instructor_id': fields.many2one('res.partner', string='Instructor', domain=[('instructor', '=', True)], required=True), 'course_id': fields.many2one('openacademy.course', string='Curso', ondelete='cascade'), 'attendee_ids': fields.one2many('openacademy.attendee', 'session_id', string='Asistentes'), 'taken_seats_percent': fields.function(_take_seats_percent, type='float', string='Taken Seats'), 'end_date': fields.function(_determin_end_date, type='date', string="End Date", fnct_inv=_set_end_date), 'hours': fields.function(_determin_hours_from_duration, type='float', string='Hours', fnct_inv=_set_hours), 'attendee_count': fields.function(_get_attendee_count, type='integer', string='Attendee Count', store=True), 'color': fields.integer('Color'), 'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done')], string='State'), } _defaults = { 'active': True, 'start_date': fields.date.today, 'state': 'draft', } _constraints = [(_check_instructor_not_in_attendees, "El instructor no puede ser asistente", ['instructor_id', 'attendee_ids'])]
asset_lines_obj.write(cr, uid, asset_line.get('id'), {'move_check': True, 'move_id': created_id}) logging.getLogger(self._name).info("""account.move.line created for {0}""".format(asset_name)) except: logging.getLogger('account.asset.asset').error( """ERROR creating the entries of account move from {0}.""".format(__name__)) raise orm.except_orm('Error', 'Failure creating the' ' account move lines.') else: logging.getLogger(self._name).info("Este activo ya esta asentado!") _columns = { 'asset_code': fields.char('Codigo', size=32, required=False, readonly=False), 'category_id': fields.many2one('account.asset.category', 'Asset Category', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}, domain=[('type','=','normal')]), 'category_parent_id': fields.many2one("account.asset.category", string="Categoria Padre del Activo", required=False, readonly=True, states={'draft':[('readonly',False)]}, domain=[('type','=','view')] ), 'account_analytic_id': fields.many2one("account.analytic.account", string="Cuenta analitica", required=True, domain=[('type','=','normal')]), 'asset_move_ids': fields.one2many('account.asset.move', 'asset_id','Movimientos'), #'asset_move_ids': fields.one2many('account.asset.move', 'asset_id', 'Movements') } _defaults = { 'asset_code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'asset.number') }
class account_voucher(osv.osv): _inherit = 'account.voucher' #set the account for the selected partner def onchange_od_partner_id(self, cr, uid, ids, partner_id, context=None): res = {} if partner_id: partner = self.pool.get('res.partner').browse(cr, uid, partner_id) # print "###############",partner # writeoff_acc_id = partner. # return {'value': {'writeoff_acc_id': writeoff_acc_id}} return res def onchange_od_group_pay(self, cr, uid, ids, od_group_pay, context=None): return {'value': {'partner_id': ''}} _columns = { 'od_partner_id': fields.many2one('res.partner', 'Partner'), 'od_populate': fields.selection([('dr', 'Debit'), ('cr', 'Credit')], 'Allocation'), 'od_group_pay': fields.boolean('Pay as Group', readonly=True, states={'draft': [('readonly', False)]}), 'od_payee': fields.char('Payee', readonly=True, states={'draft': [('readonly', False)]}), 'od_acc_payee': fields.boolean('A/c Payee', readonly=True, states={'draft': [('readonly', False)]}) } #partner selection in diff amount writeoff def writeoff_move_line_get(self, cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context=None): move_line = super(account_voucher, self).writeoff_move_line_get(cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context=None) voucher = self.pool.get('account.voucher').browse( cr, uid, voucher_id, context) if voucher.state == 'draft' and voucher.pdc_check and voucher.od_with_out_allocaion: # partner_rec_acc_id = voucher.partner_id.property_account_receivable.id # partner_payable_acc_id = voucher.partner_id.property_account_payable.id mvl_acc_id = move_line.get('account_id') # if mvl_acc_id and mvl_acc_id == partner_rec_acc_id: move_line[ 'account_id'] = voucher.od_check_clearing_acc_id and voucher.od_check_clearing_acc_id.id or move_line.get( 'account_id') if voucher.od_partner_id and voucher.od_partner_id.id: move_line[ 'partner_id'] = voucher.od_partner_id and voucher.od_partner_id.id return move_line def od_deallocate(self, cr, uid, ids, context=None): ctx = context.copy() for voucher in self.browse(cr, uid, ids, context): voucher.line_cr_ids.unlink() voucher.line_dr_ids.unlink() voucher_cr_lines = [] voucher_dr_lines = [] partner_id = voucher.partner_id and voucher.partner_id.id journal_id = voucher.journal_id and voucher.journal_id.id price = voucher.amount or 0.0 currency_id = voucher.currency_id and voucher.currency_id.id ttype = voucher.type rate = voucher.payment_rate date = voucher.date ctx.update({'date': date}) payment_rate_currency_id = voucher.payment_rate_currency_id and voucher.payment_rate_currency_id.id voucher_rate = self.pool.get('res.currency').read( cr, uid, [currency_id], ['rate'], context=ctx)[0]['rate'] ctx.update({ 'voucher_special_currency': payment_rate_currency_id, 'voucher_special_currency_rate': rate * voucher_rate, }) res = self.od_recompute_voucher_lines(cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context=ctx) cr_lines = res['value'].get('line_cr_ids') dr_lines = res['value'].get('line_dr_ids') # if cr_lines and voucher.od_populate == 'cr': # for line in cr_lines: # voucher_cr_lines.append([0,0,line]) # elif dr_lines and voucher.od_populate == 'dr': # for line in dr_lines: # voucher_dr_lines.append([0,0,line]) # else: for line in cr_lines: voucher_cr_lines.append([0, 0, line]) for line in dr_lines: voucher_dr_lines.append([0, 0, line]) voucher.write({ 'line_cr_ids': voucher_cr_lines, 'line_dr_ids': voucher_dr_lines }) print "!!!!!!!~~~~~~~**", res return res return self.od_recompute_voucher_lines(cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context=ctx) # to avoid automatic Allocation def recompute_voucher_lines(self, cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context=None): #set default values default = { 'value': { 'line_dr_ids': [], 'line_cr_ids': [], 'pre_line': False }, } return default #automatic alocation is overide to allocate manually def od_recompute_voucher_lines(self, cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context=None): if context is None: context = {} if context.get('od_manual_allocate'): return {} """ Returns a dict that contains new values and context @param partner_id: latest value from user input for field partner_id @param args: other arguments @param context: context arguments, like lang, time zone @return: Returns a dict which contains new values, and context """ def _remove_noise_in_o2m(): """if the line is partially reconciled, then we must pay attention to display it only once and in the good o2m. This function returns True if the line is considered as noise and should not be displayed """ if line.reconcile_partial_id: if currency_id == line.currency_id.id: if line.amount_residual_currency <= 0: return True else: if line.amount_residual <= 0: return True return False if context is None: context = {} context_multi_currency = context.copy() currency_pool = self.pool.get('res.currency') move_line_pool = self.pool.get('account.move.line') partner_pool = self.pool.get('res.partner') journal_pool = self.pool.get('account.journal') line_pool = self.pool.get('account.voucher.line') #set default values default = { 'value': { 'line_dr_ids': [], 'line_cr_ids': [], 'pre_line': False }, } # drop existing lines line_ids = ids and line_pool.search(cr, uid, [('voucher_id', '=', ids[0])]) for line in line_pool.browse(cr, uid, line_ids, context=context): if line.type == 'cr': default['value']['line_cr_ids'].append((2, line.id)) else: default['value']['line_dr_ids'].append((2, line.id)) if not partner_id or not journal_id: return default journal = journal_pool.browse(cr, uid, journal_id, context=context) partner = partner_pool.browse(cr, uid, partner_id, context=context) currency_id = currency_id or journal.company_id.currency_id.id total_credit = 0.0 total_debit = 0.0 account_type = None if context.get('account_id'): account_type = self.pool['account.account'].browse( cr, uid, context['account_id'], context=context).type if ttype == 'payment': if not account_type: account_type = 'payable' total_debit = price or 0.0 else: total_credit = price or 0.0 if not account_type: account_type = 'receivable' ##Custom Code move_search_domain = [('state', '=', 'valid'), ('account_id.type', '=', account_type), ('reconcile_id', '=', False), ('partner_id', '=', partner_id)] if context.get('od_group_pay'): move_search_domain = [('state', '=', 'valid'), ('account_id.type', '=', account_type), ('reconcile_id', '=', False), ('partner_id', 'child_of', partner_id)] if not context.get('move_line_ids', False): ids = move_line_pool.search(cr, uid, move_search_domain, context=context) else: ids = context['move_line_ids'] invoice_id = context.get('invoice_id', False) company_currency = journal.company_id.currency_id.id move_lines_found = [] #order the lines by most old first ids.reverse() account_move_lines = move_line_pool.browse(cr, uid, ids, context=context) #compute the total debit/credit and look for a matching open amount or invoice for line in account_move_lines: if _remove_noise_in_o2m(): continue if invoice_id: if line.invoice.id == invoice_id: #if the invoice linked to the voucher line is equal to the invoice_id in context #then we assign the amount on that line, whatever the other voucher lines move_lines_found.append(line.id) elif currency_id == company_currency: #otherwise treatments is the same but with other field names if line.amount_residual == price: #if the amount residual is equal the amount voucher, we assign it to that voucher #line, whatever the other voucher lines move_lines_found.append(line.id) break #otherwise we will split the voucher amount on each line (by most old first) total_credit += line.credit or 0.0 total_debit += line.debit or 0.0 elif currency_id == line.currency_id.id: if line.amount_residual_currency == price: move_lines_found.append(line.id) break total_credit += line.credit and line.amount_currency or 0.0 total_debit += line.debit and line.amount_currency or 0.0 remaining_amount = price #voucher line creation for line in account_move_lines: if _remove_noise_in_o2m(): continue if line.currency_id and currency_id == line.currency_id.id: amount_original = abs(line.amount_currency) amount_unreconciled = abs(line.amount_residual_currency) else: #always use the amount booked in the company currency as the basis of the conversion into the voucher currency amount_original = currency_pool.compute( cr, uid, company_currency, currency_id, line.credit or line.debit or 0.0, context=context_multi_currency) amount_unreconciled = currency_pool.compute( cr, uid, company_currency, currency_id, abs(line.amount_residual), context=context_multi_currency) line_currency_id = line.currency_id and line.currency_id.id or company_currency rs = { 'name': line.move_id.name, 'type': line.credit and 'dr' or 'cr', 'move_line_id': line.id, 'account_id': line.account_id.id, 'amount_original': amount_original, 'amount': 0.0, #custom 'date_original': line.date, 'date_due': line.date_maturity, 'amount_unreconciled': amount_unreconciled, 'currency_id': line_currency_id, 'od_partner_id': line.partner_id and line.partner_id.id, #Custom Code } remaining_amount -= rs['amount'] #in case a corresponding move_line hasn't been found, we now try to assign the voucher amount #on existing invoices: we split voucher amount by most old first, but only for lines in the same currency if not move_lines_found: if currency_id == line_currency_id: if line.credit: amount = min(amount_unreconciled, abs(total_debit)) rs['amount'] = 0.0 total_debit -= amount else: amount = min(amount_unreconciled, abs(total_credit)) rs['amount'] = 0.0 total_credit -= amount if rs['amount_unreconciled'] == rs['amount']: rs['reconcile'] = True if rs['type'] == 'cr': default['value']['line_cr_ids'].append(rs) else: default['value']['line_dr_ids'].append(rs) if len(default['value']['line_cr_ids']) > 0: default['value']['pre_line'] = 1 elif len(default['value']['line_dr_ids']) > 0: default['value']['pre_line'] = 1 default['value'][ 'writeoff_amount'] = self._compute_writeoff_amount( cr, uid, default['value']['line_dr_ids'], default['value']['line_cr_ids'], price, ttype) return default
# -*- coding: utf-8 -*- from openerp.osv import fields, orm import datetime class manuscrito(orm.Model): _name = 'res.manuscrito' _description = 'Manuscrito' _columns = { 'autor': fields.many2one('res.partner', 'Autor', track_visibility='onchange',required=True, select=True),domain="[('author','=',True)]"), 'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null', track_visibility='onchange', select=True, help="Linked partner (optional). Usually created when converting the lead."), 'titulo': fields.char('Título', size=50, required=True), 'isbn':fields.char('ISBN', size=30, required=True), 'formato':fields.char('Formato', size=30), 'genero':fields.selection([('ciencia-ficcion','Ciencia-Ficcion'),('novela','Novela'),('poesia','Poesía'),('cuento','Cuento'),('historia','Historia'),('miedo','Miedo'),('otro','Otros')],'Género', required=True), 'email':fields.char('E-MAIL',size=20), 'comment': fields.text('Descripción'), 'image': fields.binary("Image", help="Select image here"), 'date': fields.date('Date', select=1), 'idioma':fields.selection([('cas','Castellano'),('en','Inglés'),('fr','Francés')],'Idioma'), 'state': fields.selection([('recibo', 'Acuse recibo'),('eval', 'Evaluación'),('confirmacion','Pendiente confirmación'),('cancelled', 'Cancelado'),('firma', 'Firma Contrato'),('corregir', 'Corrección'),('reenvio', 'Visto bueno autor'),('envio imprenta', 'Enviado a imprenta'), ('done', 'Hecho')]), } def set_recibo(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'eval'}, context=context) def set_evaluar(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'confirmacion'}, context=context) def set_aceptar(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'firma'}, context=context) def set_firmar(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'corregir'}, context=context)
class account_voucher_line(osv.osv): _inherit = 'account.voucher.line' _columns = { 'od_partner_id': fields.many2one('res.partner', 'Partner'), }
def _setup_analytic_fields(cls, analytic, para, columns, defaults, orm_name, name, bases, nmspc): """Generate analytic and para-analytic fields on the model.""" # If _analytic uses a shortcut, convert it into a prefix-model mapping. if analytic is True: analytic = {"a": orm_name.replace(".", "_")} elif isinstance(analytic, basestring): analytic = {"a": analytic} # Create a field that will be used for replacement in the view if analytic: columns["analytic_dimensions"] = fields.function( lambda self, cr, uid, ids, *a: {i: "" for i in ids}, string=u"Analytic Dimensions", readonly=True, store=False, ) col_pattern = "{pre}{n}_{suf}" size = int(config.get_misc("analytic", "analytic_size", 5)) # Generate the fields directly into the _columns attribute. all_analytic = [] for prefix, model_name in analytic.iteritems(): # Analytic fields all_analytic.append((model_name, prefix, "id")) for n in xrange(1, size + 1): col_name = col_pattern.format(pre=prefix, n=n, suf="id") domain_field = "nd_id.ns{n}_id.model_name".format(n=n) columns[col_name] = fields.many2one( "analytic.code", "Generated Analytic Field", domain=[ (domain_field, "=", model_name), ("view_type", "=", False), ("disabled_per_company", "=", False), ], track_visibility="onchange", ) for key, value in para.iteritems(): # Para-analytic fields prefix, suffix = key model_name = value["model"] all_analytic.append((model_name, prefix, suffix)) if suffix == "id": raise ValueError("Para-analytic suffix cannot be 'id'") field_type = value["type"] args = value["args"] kwargs = value["kwargs"] for n in xrange(1, size + 1): col_name = col_pattern.format(pre=prefix, n=n, suf=suffix) columns[col_name] = field_type(*args, **kwargs) if "default" in value: defaults[col_name] = value["default"] # In order to preserve inheritance, possible overrides, and OEMetaSL's # expected behavior, work on a new class that inherits the given bases, # then make our model class inherit from this class. superclass_name = "_{name}_SuperAnalytic".format(name=name) # Set _register to False in order to prevent its instantiation. superclass = type(superclass_name, bases, {"_register": False}) @AddMethod(superclass) def fields_get(self, cr, uid, allfields=None, context=None, write_access=True): """Override this method to rename analytic fields.""" res = super(superclass, self).fields_get( cr, uid, allfields=allfields, context=context, write_access=write_access ) analytic_osv = self.pool.get("analytic.structure") for model_name, prefix, suffix in all_analytic: res = analytic_osv.analytic_fields_get(cr, uid, model_name, res, prefix, suffix, context=context) return res @AddMethod(superclass) def fields_view_get(self, cr, uid, view_id=None, view_type="form", context=None, toolbar=False, submenu=False): """Override this method to hide unused analytic fields.""" res = super(superclass, self).fields_view_get( cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu ) analytic_osv = self.pool.get("analytic.structure") for model_name, prefix, suffix in all_analytic: res = analytic_osv.analytic_fields_view_get(cr, uid, model_name, res, prefix, suffix, context=context) return res return (superclass,)
class MailMessage(osv.Model): _name = "sale.comment" _description = "Sale Comment" _columns = { 'comment_date': fields.datetime('Comment Date'), 'seller_reply_date': fields.datetime('Seller Reply Date'), 'chase_comment_date': fields.datetime('Chase Comment Date'), 'comment_body': fields.html('Comment Contents', help='Automatically sanitized HTML contents'), 'seller_reply_body': fields.html('Seller Reply Contents', help='Automatically sanitized HTML contents'), 'chase_comment_body': fields.html('Chase Comment Contents', help='Automatically sanitized HTML contents'), 'rating': fields.integer("Rating"), 'order_id': fields.many2one('sale.order', "Related Sale Order ID"), 'order_line_id': fields.many2one('sale.order.line', "Related Sale Order Line ID"), 'author_id': fields.many2one('res.partner', 'Author', help="Author of the comment."), 'product_tmp_id': fields.many2one('product.template', "Related Product Template ID"), 'website_published': fields.boolean( 'Published', help="Visible on the website as a comment", copy=False, ), 'is_anonymous': fields.boolean('Is Anonymous', default=False), 'wait_business_reply': fields.boolean('Wait for the business reply', default=True), } def _prepare_comment(self, cr, uid, line_id, context=None): line_obj = self.pool.get('sale.order.line') if context is None: context = {} description = context.get('description') rating = context.get('rating') website_published = context.get('website_published') is_anonymous = context.get('is_anonymous') values = {} for line in line_obj.browse(cr, uid, line_id, context=context): values['comment_date'] = time.strftime("%Y-%m-%d %H:%M:%S") values['comment_body'] = description values['rating'] = rating values['order_id'] = line.order_id.id values['order_line_id'] = line.id values['author_id'] = line.order_partner_id.id values['product_tmp_id'] = line.product_id.product_tmpl_id.id values['website_published'] = website_published values['is_anonymous'] = is_anonymous values['wait_business_reply'] = True return values def create_comment(self, cr, uid, line_id, context=None): """Create the comment by those values :param line_id: sale order line ID(int) """ if context is None: context = {} value = self._prepare_comment(cr, uid, line_id, context=context) comm_ids = self.create(cr, uid, value, context=context) return comm_ids
for this in self.browse(cr, uid, ids, context=context): res[this.id] = this.invoice_lines and \ all(iline.invoice_id.state != 'cancel' for iline in this.invoice_lines) return res def _order_lines_from_invoice(self, cr, uid, ids, context=None): # direct access to the m2m table is the less convoluted way to achieve this (and is ok ACL-wise) cr.execute("""SELECT DISTINCT sol.id FROM sale_order_invoice_rel rel JOIN sale_order_line sol ON (sol.order_id = rel.order_id) WHERE rel.invoice_id = ANY(%s)""", (list(ids),)) return [i[0] for i in cr.fetchall()] _name = 'sale.order.line' _description = 'Sales Order Line' _columns = { 'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}), 'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."), 'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True), 'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True), 'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean', store={ 'account.invoice': (_order_lines_from_invoice, ['state'], 10), 'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10)}), 'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}), 'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="From stock: When needed, the product is taken from the stock or we wait for replenishment.\nOn order: When needed, the product is purchased or produced."), 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')), 'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}), 'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner',help="A partner to whom the particular product needs to be allotted."), 'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), required=True, readonly=True, states={'draft': [('readonly', False)]}),
class generate_pr_wizard(osv.osv_memory): _name = 'generate.pr.wizard' _description = 'Generate PR Wizard' _columns = { 'delivery_date': fields.date('Delivery Date', required=True), 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True), } def _get_bom_line(self, cr, uid, order_line): return { 'item_no': order_line.item_no, 'part_name': order_line.name, 'description': order_line.description, 'erp_no': order_line.erp_no, 'standard': order_line.standard, 'material': order_line.material, 'thickness': order_line.thickness, 'work_steps': order_line.work_steps, 'part_type': order_line.part_type, 'bom_qty': order_line.bom_qty, 'quantity': getattr(order_line, "%s_need_qty" % order_line.last_step, 0), 'product_id': order_line.product_id, } def _create_pr(self, cr, uid, pr_vals): pur_req_obj = self.pool.get('pur.req') return pur_req_obj.create(cr, uid, pr_vals) def _create_pr_line(self, cr, uid, pr_id, bom_line, sequence, delivery_date, drawing_order_id = False,): pr_line_obj = self.pool.get('pur.req.line') po_line_obj = self.pool.get('purchase.order.line') if bom_line['part_type'] != 'PRODUCED': product = bom_line['product_id'] uom = product.uom_id or product.uom_po_id pur_req_line_vals = { 'product_id': product.id, 'product_uom_id': uom.id, 'uom_categ_id': product.uom_id.category_id.id, 'date_required': delivery_date, 'inv_qty': product.qty_available, 'req_id': pr_id, } if drawing_order_id: pur_req_line_vals.update({'drawing_order_id': drawing_order_id,}) #Check if this product already in pr lines exist_pr_line_ids = pr_line_obj.search(cr, uid, [ ('req_id','=',pr_id), ('product_id','=',product.id), ]) quantity = bom_line['quantity'] if exist_pr_line_ids: pr_line = pr_line_obj.browse(cr, uid, exist_pr_line_ids[0]) quantity += pr_line.product_qty need_to_order = 0 if quantity > product.qty_available: need_to_order = quantity - product.qty_available pr_line_obj.write(cr, uid, [pr_line.id],{ 'product_qty' : quantity, 'need_order_quantity': need_to_order, }) else: need_to_order = 0 if quantity > product.qty_available: need_to_order = quantity - product.qty_available pur_req_line_vals.update({ 'product_qty': quantity, 'sequence': sequence, 'erp_no': bom_line['erp_no'], 'item_no': bom_line['item_no'], 'name': bom_line["description"], 'material': bom_line["material"], 'standard': bom_line["standard"], 'quantity_per_unit': bom_line["bom_qty"], 'inv_qty': product.qty_available, 'reserved_quantity': 0, 'need_order_quantity': need_to_order, 'note': '', 'price': product.uom_po_price, }) purchase_order_line_ids = po_line_obj.search(cr, uid, [('product_id', '=', product.id), ('state', 'in', ['confirmed', 'approved', 'done'])], order="date_planned desc") if purchase_order_line_ids: purchase_order_line = po_line_obj.browse(cr, uid, purchase_order_line_ids)[ 0] pur_req_line_vals.update({'supplier_id': purchase_order_line.order_id.partner_id.id}) pr_line_obj.create(cr, uid, pur_req_line_vals) return True def do_generate(self, cr, uid, ids, context=None): generate_pr = self.browse(cr, uid, ids, context)[0] drawing_order_ids = context.get('drawing_order_ids', False) drawing_order_obj = self.pool.get('drawing.order') pur_req_obj = self.pool.get('pur.req') if drawing_order_ids: pr_names = [] for order in drawing_order_obj.browse(cr, uid, drawing_order_ids): pur_req_ids = pur_req_obj.search(cr, uid, [ ('drawing_order_id', '=', order.id) ]) if pur_req_ids: raise osv.except_osv(_("Error!"), _('A Purchase Requisition of this drawing order is already exist!')) pur_req_id = self._create_pr(cr, uid, { 'warehouse_id': generate_pr.warehouse_id.id, 'drawing_order_id': order.id, 'pr_type': 'mfg', 'unit': order.product_id.id, 'delivery_date': generate_pr.delivery_date, 'engineer': uid, }) pr = pur_req_obj.browse(cr, uid, pur_req_id) pr_names.append(pr.name) sequence = 1 for order_line in order.order_lines: bom_line = self._get_bom_line(cr, uid, order_line) self._create_pr_line(cr, uid, pur_req_id,bom_line,sequence,generate_pr.delivery_date,order.id) sequence += 1 return self.pool.get('warning').info(cr, uid, title='Information', message=_( "PR [%s] has been created!")% ",".join(pr_names) ) return True
else : res[user1.id] = user1.server.server_addres +':' + user1.server.rpc_port+'/web?db='+ user1.host_name.lower() return res def get_counter(self,cr,uid,context=None): myids = self.search(cr, uid, [], context=context) for user in self.browse(cr,uid,myids,context=context): res = user.counter +1; isTrue = self.write(cr, uid, user.id, {'counter': res}, context=context) return isTrue _name = "saas.user.info" _description = "saas.user.info" _columns = { 'name': fields.char('Note', required=False,track_visibility='always', help=""), 'user': fields.many2one('res.partner', 'partner', help=""), 'host_name': fields.char('host_name',required=True, help=""), 'host_type': fields.char('host_type',required=False , help=""), 'server': fields.many2one('saas.server', 'server',required=True, help=""), 'url_addres': fields.function(_get_full_url, type='char',string='url_addres'), 'start_date': fields.datetime('start_date',required=False, help=""), 'end_date': fields.function(_compute_exp_date, type = 'datetime',string='end_date'), 'product_id':fields.many2one('product.product','product_id',required = False,help=''), 'state': fields.function(_get_server_state, type='char', string='state'), 'counter': fields.integer('counter',required=False , help=""), } _defaults = { 'start_date': fields.datetime.now, } _sql_constraints = [ ('host_name_uniq', 'unique (host_name)', 'host_name must be unique !'),
class product_template(Model): _inherit = "product.template" _columns = { 'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'), }
try: proxy = self.pool.get("ir.model.data") result = proxy.get_object_reference(cr, uid, "product", "product_uom_unit") return result[1] except Exception, ex: return False _name = "rent.order.line" _description = "Rent Order Line" _columns = { "name": fields.text("Description", required=True, readonly=True, states={"draft": [("readonly", False)]}), "order_id": fields.many2one( "rent.order", "Rent Reference", required=True, ondelete="cascade", select=True, readonly=True, states={"draft": [("readonly", False)]}, ), "sequence": fields.integer("Sequence"), "product_id": fields.many2one( "product.product", "Product", domain=[("is_rent", "=", True)], change_default=True ), "invoice_lines": fields.many2many( "account.invoice.line", "rent_order_line_invoice_rel", "order_line_id", "invoice_id", "Invoice Lines", readonly=True,
class crm_phonecall2phonecall(osv.osv_memory): _name = 'crm.phonecall2phonecall' _description = 'Phonecall To Phonecall' _columns = { 'name' : fields.char('Call summary', required=True, select=1), 'user_id' : fields.many2one('res.users',"Assign To"), 'contact_name':fields.char('Contact'), 'phone':fields.char('Phone'), 'categ_id': fields.many2one('crm.case.categ', 'Category', \ domain="['|',('team_id','=',False),('team_id','=',team_id),\ ('object_id.model', '=', 'crm.phonecall')]"), 'date': fields.datetime('Date'), 'team_id':fields.many2one('crm.case.section','Sales Team'), 'action': fields.selection([('schedule','Schedule a call'), ('log','Log a call')], 'Action', required=True), 'partner_id' : fields.many2one('res.partner', "Partner"), 'note':fields.text('Note') } def action_cancel(self, cr, uid, ids, context=None): """ Closes Phonecall to Phonecall form """ return {'type':'ir.actions.act_window_close'} def action_schedule(self, cr, uid, ids, context=None): value = {} if context is None: context = {} phonecall = self.pool.get('crm.phonecall') phonecall_ids = context and context.get('active_ids') or [] for this in self.browse(cr, uid, ids, context=context): phocall_ids = phonecall.schedule_another_phonecall(cr, uid, phonecall_ids, this.date, this.name, \ this.user_id and this.user_id.id or False, \ this.team_id and this.team_id.id or False, \ this.categ_id and this.categ_id.id or False, \ action=this.action, context=context) return phonecall.redirect_phonecall_view(cr, uid, phocall_ids[phonecall_ids[0]], context=context) def default_get(self, cr, uid, fields, context=None): """ This function gets default values """ res = super(crm_phonecall2phonecall, self).default_get(cr, uid, fields, context=context) record_id = context and context.get('active_id', False) or False res.update({'action': 'schedule', 'date': time.strftime('%Y-%m-%d %H:%M:%S')}) if record_id: phonecall = self.pool.get('crm.phonecall').browse(cr, uid, record_id, context=context) categ_id = False data_obj = self.pool.get('ir.model.data') try: res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2') categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id except ValueError: pass if 'name' in fields: res.update({'name': phonecall.name}) if 'user_id' in fields: res.update({'user_id': phonecall.user_id and phonecall.user_id.id or False}) if 'date' in fields: res.update({'date': False}) if 'team_id' in fields: res.update({'team_id': phonecall.team_id and phonecall.team_id.id or False}) if 'categ_id' in fields: res.update({'categ_id': categ_id}) if 'partner_id' in fields: res.update({'partner_id': phonecall.partner_id and phonecall.partner_id.id or False}) return res
'type': fields.selection([ ('payable','Payable'), ('receivable','Receivable'), ],'Type', readonly=True, select=True), # invisible field to filter payment order lines by payment type 'payment_type_name': fields.function(_payment_type_name_get, method=True, type="char", size=64, string="Payment type name"), # The field name is necessary to add attachement documents to payment orders 'name': fields.function(_name_get, method=True, type="char", size=64, string="Name"), 'create_account_moves': fields.selection([('bank-statement','Bank Statement'),('direct-payment','Direct Payment')], 'Create Account Moves', required=True, states={'done':[('readonly',True)]}, help='Indicates when account moves should be created for order payment lines. "Bank Statement" '\ 'will wait until user introduces those payments in bank a bank statement. "Direct Payment" '\ 'will mark all payment lines as payied once the order is done.'), 'period_id': fields.many2one('account.period', 'Period', states={'done':[('readonly',True)]}), } _defaults = { 'type': _get_type, 'reference': _get_reference, 'create_account_moves': lambda *a: 'bank-statement', 'period_id': _get_period, } def cancel_from_done(self, cr, uid, ids, context=None): if context is None: context = {} #Search for account_moves remove = [] for move in self.browse(cr,uid,ids,context):
class ResCompany(orm.Model): _inherit = 'res.company' _columns = { 'colipostefr_account': fields.char( 'Compte Principal', size=6, help=u"Nombre à 6 caractères.\n" u"La valeur par défaut est 964744"), 'colipostefr_world_account': fields.char( 'Compte International', size=6, help=u"Nombre à 6 caractères.\n" u"La valeur par défaut est 964744\n" u"Potentiellement c'est le même N° que le compte principal." u"Dans ce cas, vous pouvez laisser ce champ vide."), 'colipostefr_support_city': fields.char( 'Site de Prise en Charge', size=64, help="Site de prise en charge de la poste pour son client.\n" "Indiquer votre propre centre de rattachement"), 'colipostefr_support_city_code': fields.char( 'Code Site de Prise en Charge', size=6, help="Utile uniquement pour le module colissimo EDI " "(facultatif cependant)"), 'colipostefr_password': fields.char( 'mot de passe site web', help=u"le mot de passe doit être identique " u"à celui de votre espace client.\n" u"uniquement nécessaire pour les envois à l'étranger.\n" u"mettre un mot de passe complexe"), 'colipostefr_unittest_helper': fields.boolean( 'Unit Test Helper', help=u"Seulement utile pour les développeurs.\n" u"Si coché enregistre les données du picking ColiPoste\n" u"dans le dossier temporaire système du serveur.\n" u"Ce fichier peut être utilisé pour créer " u"de nouveaux tests unitaires python"), 'colipostefr_webservice_message': fields.boolean( u'Enregistre les Messages du Webservice', help=u"Pour ColiPoste International. \nSi coché, un commentaire " u"sera créé dans le bon de livraison\nsi la réponse du " u"web service contient un message additionnel."), 'colipostefr_repo_task_id': fields.many2one( 'repository.task', string=u"Tâche EDI", help=u"Liaison à la tâche qui exporte le fichier EDI.\n" u"Ne pas créer de tâche spécifique ici.\n" u"La valeur par défaut pour la principale société d'Odoo " u"ne doit pas changer.\nUtilisez une tâche créée " u"depuis le repository 'La Poste EDI'\n" u"(Configuration > File Exchange > File Repositories " u"> La Poste EDI)"), } _defaults = { 'colipostefr_account': '', 'colipostefr_support_city': '... PFC', 'colipostefr_password': '', 'colipostefr_unittest_helper': False, 'colipostefr_webservice_message': True, }
if res[1]: user_id = res[0] elif conf["create_user"]: _logger.debug('Creating new OpenERP user "%s" from LDAP' % login) user_obj = self.pool.get("res.users") values = self.map_ldap_attributes(cr, uid, conf, login, ldap_entry) if conf["user"]: user_id = user_obj.copy(cr, SUPERUSER_ID, conf["user"], default={"active": True}) user_obj.write(cr, SUPERUSER_ID, user_id, values) else: user_id = user_obj.create(cr, SUPERUSER_ID, values) return user_id _columns = { "sequence": fields.integer("Sequence"), "company": fields.many2one("res.company", "Company", required=True, ondelete="cascade"), "ldap_server": fields.char("LDAP Server address", size=64, required=True), "ldap_server_port": fields.integer("LDAP Server port", required=True), "ldap_binddn": fields.char( "LDAP binddn", size=64, help=( "The user account on the LDAP server that is used to query " "the directory. Leave empty to connect anonymously." ), ), "ldap_password": fields.char( "LDAP password", size=64, help=("The password of the user account on the LDAP server that is " "used to query the directory."), ),
class hr_applicant(osv.Model): _name = "hr.applicant" _description = "Applicant" _order = "id desc" _inherit = ['mail.thread', 'ir.needaction_mixin'] _track = { 'stage_id': { # this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages 'hr_recruitment.mt_applicant_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id. sequence <= 1, 'hr_recruitment.mt_applicant_stage_changed': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id. sequence > 1, }, } _mail_mass_mailing = _('Applicants') def _get_default_department_id(self, cr, uid, context=None): """ Gives default department by checking if present in the context """ return (self._resolve_department_id_from_context( cr, uid, context=context) or False) def _get_default_stage_id(self, cr, uid, context=None): """ Gives default stage_id """ department_id = self._get_default_department_id(cr, uid, context=context) return self.stage_find(cr, uid, [], department_id, [('fold', '=', False)], context=context) def _resolve_department_id_from_context(self, cr, uid, context=None): """ Returns ID of department based on the value of 'default_department_id' context key, or None if it cannot be resolved to a single department. """ if context is None: context = {} if type(context.get('default_department_id')) in (int, long): return context.get('default_department_id') if isinstance(context.get('default_department_id'), basestring): department_name = context['default_department_id'] department_ids = self.pool.get('hr.department').name_search( cr, uid, name=department_name, context=context) if len(department_ids) == 1: return int(department_ids[0][0]) return None def _get_default_company_id(self, cr, uid, department_id=None, context=None): company_id = False if department_id: department = self.pool['hr.department'].browse(cr, uid, department_id, context=context) company_id = department.company_id.id if department and department.company_id else False if not company_id: company_id = self.pool['res.company']._company_default_get( cr, uid, 'hr.applicant', context=context) return company_id def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None): access_rights_uid = access_rights_uid or uid stage_obj = self.pool.get('hr.recruitment.stage') order = stage_obj._order # lame hack to allow reverting search, should just work in the trivial case if read_group_order == 'stage_id desc': order = "%s desc" % order # retrieve section_id from the context and write the domain # - ('id', 'in', 'ids'): add columns that should be present # - OR ('department_id', '=', False), ('fold', '=', False): add default columns that are not folded # - OR ('department_id', 'in', department_id), ('fold', '=', False) if department_id: add department columns that are not folded department_id = self._resolve_department_id_from_context( cr, uid, context=context) search_domain = [] if department_id: search_domain += ['|', ('department_id', '=', department_id)] search_domain += [ '|', ('id', 'in', ids), ('department_id', '=', False) ] stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context) result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context) # restore order of the search result.sort( lambda x, y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0]))) fold = {} for stage in stage_obj.browse(cr, access_rights_uid, stage_ids, context=context): fold[stage.id] = stage.fold or False return result, fold def _compute_day(self, cr, uid, ids, fields, args, context=None): """ @param cr: the current row, from the database cursor, @param uid: the current user’s ID for security checks, @param ids: List of Openday’s IDs @return: difference between current date and log date @param context: A standard dictionary for contextual values """ res = {} for issue in self.browse(cr, uid, ids, context=context): for field in fields: res[issue.id] = {} duration = 0 ans = False hours = 0 if field in ['day_open']: if issue.date_open: date_create = datetime.strptime( issue.create_date, "%Y-%m-%d %H:%M:%S") date_open = datetime.strptime(issue.date_open, "%Y-%m-%d %H:%M:%S") ans = date_open - date_create elif field in ['day_close']: if issue.date_closed: date_create = datetime.strptime( issue.create_date, "%Y-%m-%d %H:%M:%S") date_close = datetime.strptime(issue.date_closed, "%Y-%m-%d %H:%M:%S") ans = date_close - date_create if ans: duration = float(ans.days) res[issue.id][field] = abs(float(duration)) return res def _get_attachment_number(self, cr, uid, ids, fields, args, context=None): res = dict.fromkeys(ids, 0) for app_id in ids: res[app_id] = self.pool['ir.attachment'].search_count( cr, uid, [('res_model', '=', 'hr.applicant'), ('res_id', '=', app_id)], context=context) return res _columns = { 'name': fields.char('Subject / Application Name', size=128, required=True), 'active': fields.boolean('Active', help="If the active field is set to false, it will allow you to hide the case without removing it."), 'description': fields.text('Description'), 'email_from': fields.char('Email', size=128, help="These people will receive email."), 'email_cc': fields.text('Watchers Emails', size=252, help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"), 'probability': fields.float('Probability'), 'partner_id': fields.many2one('res.partner', 'Contact'), 'create_date': fields.datetime('Creation Date', readonly=True, select=True), 'write_date': fields.datetime('Update Date', readonly=True), 'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage', track_visibility='onchange', domain="['|', ('department_id', '=', department_id), ('department_id', '=', False)]"), 'last_stage_id': fields.many2one('hr.recruitment.stage', 'Last Stage', help='Stage of the applicant before being in the current stage. Used for lost cases analysis.'), 'categ_ids': fields.many2many('hr.applicant_category', string='Tags'), 'company_id': fields.many2one('res.company', 'Company'), 'user_id': fields.many2one('res.users', 'Responsible', track_visibility='onchange'), 'date_closed': fields.datetime('Closed', readonly=True, select=True), 'date_open': fields.datetime('Assigned', readonly=True, select=True), 'date_last_stage_update': fields.datetime('Last Stage Update', select=True), 'date_action': fields.date('Next Action Date'), 'title_action': fields.char('Next Action', size=64), 'priority': fields.selection(AVAILABLE_PRIORITIES, 'Appreciation'), 'job_id': fields.many2one('hr.job', 'Applied Job'), 'salary_proposed_extra': fields.char('Proposed Salary Extra', size=100, help="Salary Proposed by the Organisation, extra advantages"), 'salary_expected_extra': fields.char('Expected Salary Extra', size=100, help="Salary Expected by Applicant, extra advantages"), 'salary_proposed': fields.float('Proposed Salary', help="Salary Proposed by the Organisation"), 'salary_expected': fields.float('Expected Salary', help="Salary Expected by Applicant"), 'availability': fields.integer('Availability', help="The number of days in which the applicant will be available to start working"), 'partner_name': fields.char("Applicant's Name", size=64), 'partner_phone': fields.char('Phone', size=32), 'partner_mobile': fields.char('Mobile', size=32), 'type_id': fields.many2one('hr.recruitment.degree', 'Degree'), 'department_id': fields.many2one('hr.department', 'Department'), 'survey': fields.related('job_id', 'survey_id', type='many2one', relation='survey.survey', string='Survey'), 'response_id': fields.many2one('survey.user_input', "Response", ondelete='set null', oldname="response"), 'reference': fields.char('Referred By', size=128), 'source_id': fields.many2one('hr.recruitment.source', 'Source'), 'day_open': fields.function(_compute_day, string='Days to Open', \ multi='day_open', type="float", store=True), 'day_close': fields.function(_compute_day, string='Days to Close', \ multi='day_close', type="float", store=True), 'color': fields.integer('Color Index'), 'emp_id': fields.many2one('hr.employee', string='Employee', help='Employee linked to the applicant.'), 'user_email': fields.related('user_id', 'email', type='char', string='User Email', readonly=True), 'attachment_number': fields.function(_get_attachment_number, string='Number of Attachments', type="integer"), } _defaults = { 'active': lambda *a: 1, 'user_id': lambda s, cr, uid, c: uid, 'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c), 'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c), 'company_id': lambda s, cr, uid, c: s._get_default_company_id( cr, uid, s._get_default_department_id(cr, uid, c), c), 'color': 0, 'date_last_stage_update': fields.datetime.now, } _group_by_full = {'stage_id': _read_group_stage_ids} def onchange_job(self, cr, uid, ids, job_id=False, context=None): department_id = False if job_id: job_record = self.pool.get('hr.job').browse(cr, uid, job_id, context=context) department_id = job_record and job_record.department_id and job_record.department_id.id or False user_id = job_record and job_record.user_id and job_record.user_id.id or False return {'value': {'department_id': department_id, 'user_id': user_id}} def onchange_department_id(self, cr, uid, ids, department_id=False, stage_id=False, context=None): if not stage_id: stage_id = self.stage_find(cr, uid, [], department_id, [('fold', '=', False)], context=context) return {'value': {'stage_id': stage_id}} def onchange_partner_id(self, cr, uid, ids, partner_id, context=None): data = { 'partner_phone': False, 'partner_mobile': False, 'email_from': False } if partner_id: addr = self.pool.get('res.partner').browse(cr, uid, partner_id, context) data.update({ 'partner_phone': addr.phone, 'partner_mobile': addr.mobile, 'email_from': addr.email }) return {'value': data} def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None): """ Override of the base.stage method Parameter of the stage search taken from the lead: - department_id: if set, stages must belong to this section or be a default case """ if isinstance(cases, (int, long)): cases = self.browse(cr, uid, cases, context=context) # collect all section_ids department_ids = [] if section_id: department_ids.append(section_id) for case in cases: if case.department_id: department_ids.append(case.department_id.id) # OR all section_ids and OR with case_default search_domain = [] if department_ids: search_domain += ['|', ('department_id', 'in', department_ids)] search_domain.append(('department_id', '=', False)) # AND with the domain in parameter search_domain += list(domain) # perform search, return the first found stage_ids = self.pool.get('hr.recruitment.stage').search( cr, uid, search_domain, order=order, context=context) if stage_ids: return stage_ids[0] return False def action_makeMeeting(self, cr, uid, ids, context=None): """ This opens Meeting's calendar view to schedule meeting on current applicant @return: Dictionary value for created Meeting view """ applicant = self.browse(cr, uid, ids[0], context) applicant_ids = [] if applicant.partner_id: applicant_ids.append(applicant.partner_id.id) if applicant.department_id and applicant.department_id.manager_id and applicant.department_id.manager_id.user_id and applicant.department_id.manager_id.user_id.partner_id: applicant_ids.append( applicant.department_id.manager_id.user_id.partner_id.id) category = self.pool.get('ir.model.data').get_object( cr, uid, 'hr_recruitment', 'categ_meet_interview', context) res = self.pool.get('ir.actions.act_window').for_xml_id( cr, uid, 'calendar', 'action_calendar_event', context) res['context'] = { 'default_partner_ids': applicant_ids, 'default_user_id': uid, 'default_name': applicant.name, 'default_categ_ids': category and [category.id] or False, } return res def action_start_survey(self, cr, uid, ids, context=None): context = context if context else {} applicant = self.browse(cr, uid, ids, context=context)[0] survey_obj = self.pool.get('survey.survey') response_obj = self.pool.get('survey.user_input') # create a response and link it to this applicant if not applicant.response_id: response_id = response_obj.create( cr, uid, { 'survey_id': applicant.survey.id, 'partner_id': applicant.partner_id.id }, context=context) self.write(cr, uid, ids[0], {'response_id': response_id}, context=context) else: response_id = applicant.response_id.id # grab the token of the response and start surveying response = response_obj.browse(cr, uid, response_id, context=context) context.update({'survey_token': response.token}) return survey_obj.action_start_survey(cr, uid, [applicant.survey.id], context=context) def action_print_survey(self, cr, uid, ids, context=None): """ If response is available then print this response otherwise print survey form (print template of the survey) """ context = context if context else {} applicant = self.browse(cr, uid, ids, context=context)[0] survey_obj = self.pool.get('survey.survey') response_obj = self.pool.get('survey.user_input') if not applicant.response_id: return survey_obj.action_print_survey(cr, uid, [applicant.survey.id], context=context) else: response = response_obj.browse(cr, uid, applicant.response_id.id, context=context) context.update({'survey_token': response.token}) return survey_obj.action_print_survey(cr, uid, [applicant.survey.id], context=context) def action_get_attachment_tree_view(self, cr, uid, ids, context=None): model, action_id = self.pool.get('ir.model.data').get_object_reference( cr, uid, 'base', 'action_attachment') action = self.pool.get(model).read(cr, uid, action_id, context=context) action['context'] = { 'default_res_model': self._name, 'default_res_id': ids[0] } action['domain'] = str( ['&', ('res_model', '=', self._name), ('res_id', 'in', ids)]) return action def message_get_suggested_recipients(self, cr, uid, ids, context=None): recipients = super(hr_applicant, self).message_get_suggested_recipients( cr, uid, ids, context=context) for applicant in self.browse(cr, uid, ids, context=context): if applicant.partner_id: self._message_add_suggested_recipient( cr, uid, recipients, applicant, partner=applicant.partner_id, reason=_('Contact')) elif applicant.email_from: self._message_add_suggested_recipient( cr, uid, recipients, applicant, email=applicant.email_from, reason=_('Contact Email')) return recipients def message_new(self, cr, uid, msg, custom_values=None, context=None): """ Overrides mail_thread message_new that is called by the mailgateway through message_process. This override updates the document according to the email. """ if custom_values is None: custom_values = {} val = msg.get('from').split('<')[0] defaults = { 'name': msg.get('subject') or _("No Subject"), 'partner_name': val, 'email_from': msg.get('from'), 'email_cc': msg.get('cc'), 'user_id': False, 'partner_id': msg.get('author_id', False), } if msg.get('priority'): defaults['priority'] = msg.get('priority') defaults.update(custom_values) return super(hr_applicant, self).message_new(cr, uid, msg, custom_values=defaults, context=context) def create(self, cr, uid, vals, context=None): if context is None: context = {} context['mail_create_nolog'] = True if vals.get( 'department_id') and not context.get('default_department_id'): context['default_department_id'] = vals.get('department_id') if vals.get('job_id') or context.get('default_job_id'): job_id = vals.get('job_id') or context.get('default_job_id') vals.update( self.onchange_job(cr, uid, [], job_id, context=context)['value']) obj_id = super(hr_applicant, self).create(cr, uid, vals, context=context) applicant = self.browse(cr, uid, obj_id, context=context) if applicant.job_id: name = applicant.partner_name if applicant.partner_name else applicant.name self.pool['hr.job'].message_post( cr, uid, [applicant.job_id.id], body=_('New application from %s') % name, subtype="hr_recruitment.mt_job_applicant_new", context=context) return obj_id def write(self, cr, uid, ids, vals, context=None): if isinstance(ids, (int, long)): ids = [ids] res = True # user_id change: update date_open if vals.get('user_id'): vals['date_open'] = fields.datetime.now() # stage_id: track last stage before update if 'stage_id' in vals: vals['date_last_stage_update'] = fields.datetime.now() for applicant in self.browse(cr, uid, ids, context=None): vals['last_stage_id'] = applicant.stage_id.id res = super(hr_applicant, self).write(cr, uid, [applicant.id], vals, context=context) else: res = super(hr_applicant, self).write(cr, uid, ids, vals, context=context) # post processing: if job changed, post a message on the job if vals.get('job_id'): for applicant in self.browse(cr, uid, ids, context=None): name = applicant.partner_name if applicant.partner_name else applicant.name self.pool['hr.job'].message_post( cr, uid, [vals['job_id']], body=_('New application from %s') % name, subtype="hr_recruitment.mt_job_applicant_new", context=context) # post processing: if stage changed, post a message in the chatter if vals.get('stage_id'): stage = self.pool['hr.recruitment.stage'].browse(cr, uid, vals['stage_id'], context=context) if stage.template_id: # TDENOTE: probably factorize me in a message_post_with_template generic method FIXME compose_ctx = dict(context, active_ids=ids) compose_id = self.pool['mail.compose.message'].create( cr, uid, { 'model': self._name, 'composition_mode': 'mass_mail', 'template_id': stage.template_id.id, 'same_thread': True, 'post': True, 'notify': True, }, context=compose_ctx) self.pool['mail.compose.message'].write( cr, uid, [compose_id], self.pool['mail.compose.message'].onchange_template_id( cr, uid, [compose_id], stage.template_id.id, 'mass_mail', self._name, False, context=compose_ctx)['value'], context=compose_ctx) self.pool['mail.compose.message'].send_mail( cr, uid, [compose_id], context=compose_ctx) return res def create_employee_from_applicant(self, cr, uid, ids, context=None): """ Create an hr.employee from the hr.applicants """ if context is None: context = {} hr_employee = self.pool.get('hr.employee') model_data = self.pool.get('ir.model.data') act_window = self.pool.get('ir.actions.act_window') emp_id = False for applicant in self.browse(cr, uid, ids, context=context): address_id = contact_name = False if applicant.partner_id: address_id = self.pool.get('res.partner').address_get( cr, uid, [applicant.partner_id.id], ['contact'])['contact'] contact_name = self.pool.get('res.partner').name_get( cr, uid, [applicant.partner_id.id])[0][1] if applicant.job_id and (applicant.partner_name or contact_name): applicant.job_id.write( { 'no_of_hired_employee': applicant.job_id.no_of_hired_employee + 1 }, context=context) create_ctx = dict(context, mail_broadcast=True) emp_id = hr_employee.create( cr, uid, { 'name': applicant.partner_name or contact_name, 'job_id': applicant.job_id.id, 'address_home_id': address_id, 'department_id': applicant.department_id.id or False, 'address_id': applicant.company_id and applicant.company_id.partner_id and applicant.company_id.partner_id.id or False, 'work_email': applicant.department_id and applicant.department_id.company_id and applicant.department_id.company_id.email or False, 'work_phone': applicant.department_id and applicant.department_id.company_id and applicant.department_id.company_id.phone or False, }, context=create_ctx) self.write(cr, uid, [applicant.id], {'emp_id': emp_id}, context=context) self.pool['hr.job'].message_post( cr, uid, [applicant.job_id.id], body=_('New Employee %s Hired') % applicant.partner_name if applicant.partner_name else applicant.name, subtype="hr_recruitment.mt_job_applicant_hired", context=context) else: raise osv.except_osv( _('Warning!'), _('You must define an Applied Job and a Contact Name for this applicant.' )) action_model, action_id = model_data.get_object_reference( cr, uid, 'hr', 'open_view_employee_list') dict_act_window = act_window.read(cr, uid, [action_id], [])[0] if emp_id: dict_act_window['res_id'] = emp_id dict_act_window['view_mode'] = 'form,tree' return dict_act_window def get_empty_list_help(self, cr, uid, help, context=None): context['empty_list_help_model'] = 'hr.job' context['empty_list_help_id'] = context.get('default_job_id', None) context['empty_list_help_document_name'] = _("job applicants") return super(hr_applicant, self).get_empty_list_help(cr, uid, help, context=context)
cr, uid, line.taxes_id, line.price, line.qty, line.product_id, line.back_order_id.partner_id ) cur = line.back_order_id.pricelist_id.currency_id res[line.id] = cur_obj.round(cr, uid, cur, taxes["total"]) return res def _get_uom_id(self, cr, uid, context=None): try: proxy = self.pool.get("ir.model.data") result = proxy.get_object_reference(cr, uid, "product", "product_uom_unit") return result[1] except Exception, ex: return False _columns = { # 'location_destination_id': fields.many2one('stock.location', 'Stock Destination Location'), # 'location_id': fields.many2one('stock.location', 'Stock Source Location'), "product_id": fields.many2one("product.product", "Product"), "back_order_id": fields.many2one("back.to.back.order", "Back Order"), "qty": fields.float("Quantity"), "price": fields.float("Unit Price"), "subtotal": fields.function(_amount_line, string="Subtotal", digits_compute=dp.get_precision("Account")), "taxes_id": fields.many2many("account.tax", "purchase_order_taxe", "ord_id", "tax_id", "Taxes"), "product_uom": fields.many2one("product.uom", "Product Unit of Measure", required=True), } _defaults = {"product_uom": _get_uom_id} # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class hr_job(osv.osv): _inherit = "hr.job" _name = "hr.job" _inherits = {'mail.alias': 'alias_id'} def _get_attached_docs(self, cr, uid, ids, field_name, arg, context=None): res = {} attachment_obj = self.pool.get('ir.attachment') for job_id in ids: applicant_ids = self.pool.get('hr.applicant').search( cr, uid, [('job_id', '=', job_id)], context=context) res[job_id] = attachment_obj.search( cr, uid, [ '|', '&', ('res_model', '=', 'hr.job'), ('res_id', '=', job_id), '&', ('res_model', '=', 'hr.applicant'), ('res_id', 'in', applicant_ids) ], context=context) return res def _count_all(self, cr, uid, ids, field_name, arg, context=None): Applicant = self.pool['hr.applicant'] return { job_id: { 'application_count': Applicant.search_count(cr, uid, [('job_id', '=', job_id)], context=context), 'documents_count': len( self._get_attached_docs(cr, uid, [job_id], field_name, arg, context=context)[job_id]) } for job_id in ids } _columns = { 'survey_id': fields.many2one( 'survey.survey', 'Interview Form', help= "Choose an interview form for this job position and you will be able to print/answer this interview from all applicants who apply for this job" ), 'alias_id': fields.many2one( 'mail.alias', 'Alias', ondelete="restrict", required=True, help= "Email alias for this job position. New emails will automatically " "create new applicants for this job position."), 'address_id': fields.many2one('res.partner', 'Job Location', help="Address where employees are working"), 'application_ids': fields.one2many('hr.applicant', 'job_id', 'Applications'), 'application_count': fields.function(_count_all, type='integer', string='Applications', multi=True), 'manager_id': fields.related('department_id', 'manager_id', type='many2one', string='Department Manager', relation='hr.employee', readonly=True, store=True), 'document_ids': fields.function(_get_attached_docs, type='one2many', relation='ir.attachment', string='Applications'), 'documents_count': fields.function(_count_all, type='integer', string='Documents', multi=True), 'user_id': fields.many2one('res.users', 'Recruitment Responsible', track_visibility='onchange'), 'color': fields.integer('Color Index'), } def _address_get(self, cr, uid, context=None): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) return user.company_id.partner_id.id _defaults = {'address_id': _address_get} def _auto_init(self, cr, context=None): """Installation hook to create aliases for all jobs and avoid constraint errors.""" return self.pool.get('mail.alias').migrate_to_alias( cr, self._name, self._table, super(hr_job, self)._auto_init, 'hr.applicant', self._columns['alias_id'], 'name', alias_prefix='job+', alias_defaults={'job_id': 'id'}, context=context) def create(self, cr, uid, vals, context=None): alias_context = dict(context, alias_model_name='hr.applicant', alias_parent_model_name=self._name) job_id = super(hr_job, self).create(cr, uid, vals, context=alias_context) job = self.browse(cr, uid, job_id, context=context) self.pool.get('mail.alias').write(cr, uid, [job.alias_id.id], { 'alias_parent_thread_id': job_id, "alias_defaults": { 'job_id': job_id } }, context) return job_id def unlink(self, cr, uid, ids, context=None): # Cascade-delete mail aliases as well, as they should not exist without the job position. mail_alias = self.pool.get('mail.alias') alias_ids = [ job.alias_id.id for job in self.browse(cr, uid, ids, context=context) if job.alias_id ] res = super(hr_job, self).unlink(cr, uid, ids, context=context) mail_alias.unlink(cr, uid, alias_ids, context=context) return res def action_print_survey(self, cr, uid, ids, context=None): job = self.browse(cr, uid, ids, context=context)[0] survey_id = job.survey_id.id return self.pool.get('survey.survey').action_print_survey( cr, uid, [survey_id], context=context) def action_get_attachment_tree_view(self, cr, uid, ids, context=None): #open attachments of job and related applicantions. model, action_id = self.pool.get('ir.model.data').get_object_reference( cr, uid, 'base', 'action_attachment') action = self.pool.get(model).read(cr, uid, action_id, context=context) applicant_ids = self.pool.get('hr.applicant').search( cr, uid, [('job_id', 'in', ids)], context=context) action['context'] = { 'default_res_model': self._name, 'default_res_id': ids[0] } action['domain'] = str([ '|', '&', ('res_model', '=', 'hr.job'), ('res_id', 'in', ids), '&', ('res_model', '=', 'hr.applicant'), ('res_id', 'in', applicant_ids) ]) return action def action_set_no_of_recruitment(self, cr, uid, id, value, context=None): return self.write(cr, uid, [id], {'no_of_recruitment': value}, context=context)
class stock_fill_inventory(osv.osv_memory): _name = "stock.fill.inventory" _description = "Import Inventory" def _default_location(self, cr, uid, ids, context=None): try: location = self.pool.get("ir.model.data").get_object(cr, uid, "stock", "stock_location_stock") location.check_access_rule("read", context=context) location_id = location.id except (ValueError, orm.except_orm), e: return False return location_id or False _columns = { "location_id": fields.many2one("stock.location", "Location", required=True), "recursive": fields.boolean( "Include children", help="If checked, products contained in child locations of selected location will be included as well.", ), "set_stock_zero": fields.boolean( "Set to zero", help="If checked, all product quantities will be set to zero to help ensure a real physical inventory is done", ), } _defaults = {"location_id": _default_location} def view_init(self, cr, uid, fields_list, context=None): """ Creates view dynamically and adding fields at runtime. @param self: The object pointer.
class ids_hr_employee_separation(osv.osv): def separation_submit(self, cr, uid, ids, context=None): """Initiate workflow- submit the form. """ self._check_resignations(cr, uid, ids, context=context) users= self.pool.get('res.users') #code to update employee working status self._update_employee_working_status(cr, uid, ids, 'on_resign', context=None) resign=self.browse(cr, uid, ids, context=None) if users.has_group(cr, uid, 'ids_emp.group_location_hr'): print "------------------------------location--outer------------------------" if resign.employee_id.parent_id.parent_id.id==7626: print "------------------------------res--------------------------" url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Intiated.Please take necessary action.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/>Url:'+url, 'email_to': resign.employee_id.parent_id.work_email, 'email_from': '*****@*****.**', } else: print "------------------------------location--------------------------" url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Intiated.Please take necessary action.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/>Url:'+url, 'email_to': resign.employee_id.division.hod_email, 'email_cc': resign.employee_id.parent_id.work_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) elif users.has_group(cr, uid, 'ids_emp.group_business_head'): print "------------------------------business--------------------------" url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Intiated.Please take necessary action.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/>Url:'+url, 'email_to': resign.employee_id.division.hr_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) else: print "------------------------------manager--------------------------" url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Intiated.Please take necessary action.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/>Url:'+url, 'email_to': resign.employee_id.division.hod_email, 'email_cc': resign.employee_id.division.hr_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) return self.write(cr, uid, ids, {'state': 'confirm'}) def separation_first_validate(self, cr, uid, ids, context=None): """Validating the form by Manager and update the working status. """ self._check_validate(cr, uid, ids, context=context) #code to update employee working status self._update_employee_working_status(cr, uid, ids, 'resigned', context=None) resign=self.browse(cr, uid, ids, context=None) url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Approved.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/><br/>Url:'+url, 'email_to': resign.employee_id.parent_id.work_email, 'email_cc': resign.employee_id.division.hr_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) return self.write(cr, uid, ids, {'state':'approve'}) def separation_second_validate(self, cr, uid, ids, context=None): """Final validation by HOD. """ now=datetime.now() current = now.strftime('%Y-%m-%d') self._check_validate(cr, uid, ids, context=context) #code to update employee working status self._update_employee_working_status(cr, uid, ids, 'resigned', context=None) resign=self.browse(cr, uid, ids, context=None) if resign.last_date>current: raise osv.except_osv(_('Warning!'), _('You can not validate before last date in company!')) if resign.employee_id.parent_id.parent_id.id==7626: print "------------------------------res--------------------------" url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Intiated.Please take necessary action.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/>Url:'+url, 'email_to': resign.employee_id.parent_id.work_email, 'email_from': '*****@*****.**', } else: url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Validated.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.\<br/><br/>Url:'+url, 'email_to': resign.employee_id.parent_id.work_email, 'email_cc': resign.employee_id.division.hod_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) ee = self.pool.get('hr.employee').browse(cr, uid, resign.employee_id, context=context) emp_busi_id = self.pool.get('ids.business.information').search(cr, uid , [('employee_id','=',resign.employee_id.id)], context=context) eb = self.pool.get('ids.business.information').browse(cr, uid, emp_busi_id[0], context=context) emp_tech_id = self.pool.get('ids.technical.information').search(cr, uid , [('employee_id','=',resign.employee_id.id)], context=context) et = self.pool.get('ids.technical.information').browse(cr, uid, emp_tech_id[0], context=context) res = { 'employee_id':resign.employee_id.id, 'job_id':resign.employee_id.job_id.id, 'department_id':resign.employee_id.department_id.id, 'dob':resign.employee_id.birthday, 'division_id':resign.employee_id.division.id, 'location_id':resign.employee_id.office_location.id, 'gender':resign.employee_id.gender, 'mobile_no':resign.employee_id.mobile_phone, 'joining_date':resign.employee_id.joining_date, 'confirmation_status':resign.employee_id.confirmation_status.title(), 'resign_id':resign.id, 'capture_date':resign.capture_date, 'last_date':resign.last_date, 'email_control':eb.email_control, 'internet_control':eb.internet_control, 'remote_control':eb.remote_control, 'software_requirement':eb.software_requirements, 'application_share':eb.application_share_access, 'data_backup':eb.backup_remarks, 'allocation_it_asset':et.allocation_of_itassets or False, 'email_id_tech':et.email_created or False, 'internet_control_tech':et.internet_access_control or False, 'backup_setup_tech':et.backup_setup or False, 'software_requirement_tech': et.software_provisioning_and_access_control or False, 'application_share_tech':et.application_share_access or False, 'state':'phase1', } self.pool.get('emp.no.dues').create(cr, uid, res) return self.write(cr, uid, ids, {'state':'done'}) def separation_refuse(self, cr, uid, ids, context=None): """In case, resignation of employee is refused. """ #code to update employee working status self._update_employee_working_status(cr, uid, ids, 'working', context=None) resign=self.browse(cr, uid, ids, context=None) url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Refused.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/>Url:'+url, 'email_to': resign.employee_id.parent_id.work_email, 'email_cc': resign.employee_id.division.hr_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) return self.write(cr, uid, ids, {'state': 'cancel'}) def refuse_location(self, cr, uid, ids, context=None): """In case, resignation of employee is refused. """ #code to update employee working status self._update_employee_working_status(cr, uid, ids, 'working', context=None) resign=self.browse(cr, uid, ids, context=None) url="http://ids-erp.idsil.loc:8069/web" values = { 'subject': 'Resignation' + '-' + resign.employee_id.name, 'body_html': 'Resignation of' +' '+resign.employee_id.name+' '+'is Refused.<br/><br/><br/>Kindly do not reply.<br/>---This is auto generated email---<br/>Regards:<br/>ERP HR Team<br/>IDS Infotech LTD.<br/>Url:'+url, 'email_to': resign.employee_id.parent_id.work_email, 'email_from': '*****@*****.**', } #--------------------------------------------------------------- mail_obj = self.pool.get('mail.mail') msg_id = mail_obj.create(cr, uid, values, context=context) if msg_id: mail_obj.send(cr, uid, [msg_id], context=context) return self.write(cr, uid, ids, {'state': 'cancel'}) def _update_employee_working_status(self, cr, uid, ids, working_status, context=None): """Updating final working status. """ obj_separation = self.browse(cr, uid, ids) sep_emp_id = 0 obj_emp = self.pool.get('hr.employee') for record in obj_separation: sep_emp_id = record.employee_id.id obj_emp.write(cr, SUPERUSER_ID , [sep_emp_id], {'working_status':working_status}) def _initiated_get(self, cr, uid, context=None): emp_id = context.get('default_employee_id', False) if emp_id: return emp_id ids = self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)], context=context) if ids: return ids[0] return False _name = 'ids.hr.employee.separation' _inherit = ['mail.thread', 'ir.needaction_mixin'] _description = "Employee Separation" _columns = { 'rgn_number':fields.char('RGN Number', size=15, readonly=True), 'initiated_by': fields.many2one('hr.employee', 'Resign Initiated By', required=True), 'employee_id': fields.many2one('hr.employee', 'Employee', required=True), 'emp_code': fields.char('Employee Code', size=20), 'department_id':fields.many2one('hr.department', 'Department'), 'job_id': fields.many2one('hr.job', 'Designation'), 'confirmation_status': fields.related('employee_id', 'confirmation_status', type='char', relation='hr.employee', string='Confirmation Status', store=True, readonly=True), 'separation_type': fields.many2one('ids.hr.employee.separation.type', 'Resignation Type', required=True), 'rgn_accepted':fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')], 'Resignation Accepted', required=True), 'reason': fields.many2one('ids.hr.employee.separation.reason', 'Reason', required=True), 'eligible_rehire': fields.boolean('Eligible for rehire?'), 'capture_date': fields.date('Capture date', required=True), 'last_date': fields.date('Last date in company', required=True), # 'interview_by': fields.many2one('hr.employee', 'Interview By', required=True), 'user_id':fields.related('employee_id', 'user_id', type='many2one', relation='res.users', string='User', store=True), 'manager_id1': fields.many2one('hr.employee', 'First Approval', invisible=False, readonly=True, help='This area is automatically filled by the user who approve/validate the resignation at first level'), 'manager_id2': fields.many2one('hr.employee', 'Second Approval', invisible=False, readonly=True, help='This area is automatically filled by the user who approve/validate the resignation at second level'), 'notes': fields.text('Notes'), 'state': fields.selection([('draft', 'Draft'), ('confirm', 'Waiting for Approval'), ('approve', 'Approved'), ('done', 'Validated'), ('cancel', 'Refused')], 'Status', readonly=True), 'full_final_status': fields.selection([('pending', 'Pending'), ('done', 'Done')],'Full & Final Status'), } _rec_name = 'rgn_number' _defaults = { 'state': 'draft', 'capture_date':fields.date.context_today, 'full_final_status':'pending', #'initiated_by': _initiated_get } def create(self, cr, uid, vals, context=None): """Create the unique id used for F&F """ vals['rgn_number']=self.pool.get('ir.sequence').get(cr, uid,'ids.hr.employee.separation') res=super(ids_hr_employee_separation, self).create(cr, uid, vals) return res def write(self, cr, uid, ids, vals, context=None): """Updating final working status. """ if vals.get('full_final_status', False): if (vals['full_final_status'] == 'done'): self._update_employee_working_status(cr, uid, ids, 'exit', context=None) if (vals['full_final_status'] == 'pending'): self._update_employee_working_status(cr, uid, ids, 'resigned', context=None) res=super(ids_hr_employee_separation, self).write(cr, uid, ids, vals) return res def unlink(self, cr, uid, ids, context=None): for rec in self.browse(cr, uid, ids, context=context): if rec.state not in ['draft']: raise osv.except_osv(_('Warning!'),_('You cannot delete a resignation which is not in draft state.')) return super(ids_hr_employee_separation, self).unlink(cr, uid, ids, context) def onchange_employee_id(self, cr, uid, ids, employee_id, capture_date, context=None): """get associated values of employee onchange of employee id. """ value = {'department_id': False} notice_period_days=0 if employee_id: employee = self.pool.get('hr.employee').browse(cr, uid, employee_id) notice_period_days = int(employee.notice) last_date = datetime.strptime(capture_date, "%Y-%m-%d")+timedelta(days=notice_period_days) value['department_id'] = employee.department_id.id value['emp_code'] = employee.emp_code value['job_id'] = employee.job_id.id value['initiated_by'] = employee.parent_id.id value['initiated_by'] = employee.parent_id.id value['last_date'] = last_date if employee.employment_type_id=='regular': value['confirmation_status'] = employee.confirmation_status else: value['confirmation_status'] = 'NA' return {'value': value} def _check_resignations(self, cr, uid, ids, context=None): """Constraints on submitting resignation. """ for obj in self.browse(cr, uid, ids, context=context): res_user_id = obj.user_id.id resignation_ids = self.search(cr, uid, [('id','not in',ids),('user_id', '=', res_user_id),('state', '!=', 'refuse')], context=context) if resignation_ids: raise osv.except_osv(_('Warning!'), _('Resignation is already in progress for this employee')) return True def _check_validate(self, cr, uid, ids, context=None): """Constraints on validating resignation. """ users_obj = self.pool.get('res.users') if not users_obj.has_group(cr, uid, 'base.group_hr_manager'): for separation in self.browse(cr, uid, ids, context=context): if separation.employee_id.user_id.id == uid: raise osv.except_osv(_('Warning!'), _('You cannot approve your own Resignation.')) if (separation.manager_id1 and separation.manager_id1.user_id.id == uid) or (separation.manager_id2 and separation.manager_id2.user_id.id == uid): raise osv.except_osv(_('Warning!'), _('You have already approved the Resignation.')) return True def calculate_last_day(self, cr, uid, ids, employee_id, capture_date,context=None): """Calculate last day from date of resignation. """ notice_period_days=0 if employee_id: employee = self.pool.get('hr.employee').browse(cr, uid,employee_id) notice_period_days = int(employee.notice) last_date = datetime.strptime(capture_date, "%Y-%m-%d")+timedelta(days=notice_period_days) return {'value':{'last_date':datetime.strftime(last_date,DEFAULT_SERVER_DATE_FORMAT)}}
import os class stock_import_inventory(osv.osv_memory): _name = "stock.import.inventory" _description = "Import Inventory" def _default_location(self, cr, uid, ids, context=None): try: loc_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock') except ValueError, e: return False return location_id or False _columns = { 'location_id': fields.many2one('stock.location', 'Location', required=True), 'import_file': fields.binary('File', filters="*.xls"), #to consider the product current inventory or not, if yes then add the current inventory to the upload excel quantity as the quantity to do physical inventory 'consider_inventory': fields.boolean('Consider Current Inventory', select=True), 'all_done': fields.boolean('All Data Imported', readonly=True, select=True), 'result_line': fields.one2many('stock.import.inventory.result', 'import_id', 'Importing Result', readonly=True), 'file_template': fields.binary('Template File', readonly=True), 'file_template_name': fields.char('Template File Name'), } def _get_template(self, cr, uid, context): cur_path = os.path.split(os.path.realpath(__file__))[0] path = os.path.join(cur_path,'stock_import_template.xls') data = open(path,'rb').read().encode('base64') # data = os.path.getsize(path) return data
class reportes(osv.osv_memory): _name = "reportes" _description = "Exportar a excel" def exportar(self, cr, uid, ids, directory=".", context=None): #ExcelExportView.index() _cp_path = '/web/export/zb_excel_export' result = {} bal = [] activo = 0 pasivocapital = 0 saldo = {} bal1 = [] est = [] balanza = [] company = self.pool.get('res.company').browse(cr, uid, 1, context=context).name logo = self.pool.get('res.company').browse(cr, uid, 1, context=context).logo acc_obj = self.pool.get('account.account') move_obj = self.pool.get('account.move.line') balanza_obj = self.pool.get('account.annual.balance') #_________________________________________Busqueda de las variables utilizadas para el reporte_______________________________________________# for reporte in self.browse(cr, uid, ids, context=context): id = reporte.id #_________________________________________Declaracion de variables para realizar la consulta_________________________________________________# debit = 'debit' + reporte.mes credit = 'credit' + reporte.mes balance = 'balance' + reporte.mes #_________________________________________Consulta para sacar el reporte de Balance de comprobacion___________________________________________# if reporte.cero == True: if reporte.reporte == 'com': if reporte.mensual == True: # fiscalyear, query = ( "select account_code, account_name, account_level, initial_balance, %s, %s, %s from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s" % (debit, credit, balance, reporte.periodo.name, (int(reporte.nivel)))) cr.execute( "select account_code, account_name, account_level, initial_balance, %s, %s, %s from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s" % (debit, credit, balance, reporte.periodo.name, (int(reporte.nivel)))) resultado = cr.fetchall() registros = cr.rowcount cabeceras = { 0: 'Codigo', 1: 'Cuenta', 2: 'Nivel', 3: 'Saldo inicial', 4: 'Cargo', 5: 'Abono', 6: 'Saldo Final' } #cr.description elif reporte.mensual == False: query = ( "select account_code, account_name, account_level, initial_balance, debit1, credit1, balance1, debit2, credit2, balance2, debit3, credit3, balance3, debit4, credit4, balance4, debit5, credit5, balance5, debit6, credit6, balance6, debit7, credit7, balance7, debit8, credit8, balance8, debit9, credit9, balance9, debit10, credit10, balance10, debit11, credit11, balance11, debit12, credit12, balance12 from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s" % (reporte.periodo.name, (int(reporte.nivel)))) cr.execute( "select account_code, account_name, account_level, initial_balance, debit1, credit1, balance1, debit2, credit2, balance2, debit3, credit3, balance3, debit4, credit4, balance4, debit5, credit5, balance5, debit6, credit6, balance6, debit7, credit7, balance7, debit8, credit8, balance8, debit9, credit9, balance9, debit10, credit10, balance10, debit11, credit11, balance11, debit12, credit12, balance12 from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s" % (reporte.periodo.name, (int(reporte.nivel)))) resultado = cr.fetchall() registros = cr.rowcount cabeceras = cr.description elif reporte.cero == False: if reporte.reporte == 'com': if reporte.mensual == True: query = ( "select account_code, account_name, account_level, initial_balance, %s, %s, %s from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s and (%s) != 0" % (debit, credit, balance, reporte.periodo.name, (int(reporte.nivel)), balance)) cr.execute( "select account_code, account_name, account_level, initial_balance, %s, %s, %s from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s and (%s) != 0" % (debit, credit, balance, reporte.periodo.name, (int(reporte.nivel)), balance)) resultado = cr.fetchall() registros = cr.rowcount cabeceras = { 0: 'Codigo', 1: 'Cuenta', 2: 'Nivel', 3: 'Saldo inicial', 4: 'Cargo', 5: 'Abono', 6: 'Saldo Final' } #cr.description elif reporte.mensual == False: query = ( "select account_code, account_name, account_level, initial_balance, debit1, credit1, balance1, debit2, credit2, balance2, debit3, credit3, balance3, debit4, credit4, balance4, debit5, credit5, balance5, debit6, credit6, balance6, debit7, credit7, balance7, debit8, credit8, balance8, debit9, credit9, balance9, debit10, credit10, balance10, debit11, credit11, balance11, debit12, credit12, balance12 from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s and (balance1 + balance2 + balance3 + balance4 + balance5 + balance6 + balance7 + balance8 + balance9 + balance10 + balance11 + balance12) != 0" % (reporte.periodo.name, (int(reporte.nivel)))) cr.execute( "select account_code, account_name, account_level, initial_balance, debit1, credit1, balance1, debit2, credit2, balance2, debit3, credit3, balance3, debit4, credit4, balance4, debit5, credit5, balance5, debit6, credit6, balance6, debit7, credit7, balance7, debit8, credit8, balance8, debit9, credit9, balance9, debit10, credit10, balance10, debit11, credit11, balance11, debit12, credit12, balance12 from account_annual_balance where fiscalyear = cast(%s as text) and account_level <= %s and (balance1 + balance2 + balance3 + balance4 + balance5 + balance6 + balance7 + balance8 + balance9 + balance10 + balance11 + balance12) != 0" % (reporte.periodo.name, (int(reporte.nivel)))) resultado = cr.fetchall() registros = cr.rowcount cabeceras = cr.description #_________________________________________Consulta para sacar el reporte de Balance General_________________________________________________# if reporte.reporte == 'bal': acc_ids = acc_obj.search(cr, uid, [('type', '!=', 'view')]) for cuenta in acc_obj.browse(cr, uid, acc_ids): balance = 0 if reporte.movimiento == 1: move_ids = move_obj.search( cr, uid, [('period_id.fiscalyear_id.name', '=', reporte.periodo.name), ('account_id.id', '=', cuenta.id)]) else: move_ids = move_obj.search( cr, uid, [('period_id.fiscalyear_id.name', '=', reporte.periodo.name), ('account_id.id', '=', cuenta.id), ('state', '!=', 'draft')]) for move in move_obj.browse(cr, uid, move_ids): balance += move.debit - move.credit if round(balance, 2) != 0.0: if str(move.account_id.parent_id.code)[0:2] == '11': if len(bal) == 0: saldo = {0: '', 1: '', 2: ''} bal.append(saldo) saldo = {0: 'Activo Circulante', 1: '', 2: ''} bal.append(saldo) saldo = {0: move.account_id.name, 1: balance, 2: 'AC'} elif str(move.account_id.parent_id.code)[0:2] == '12': for af in bal: a = af if 'AF' not in str(a[2]): saldo = {0: '', 1: '', 2: ''} bal.append(saldo) saldo = {0: 'Activo Fijo', 1: '', 2: ''} bal.append(saldo) saldo = {0: move.account_id.name, 1: balance, 2: 'AF'} # bal.append(saldo) elif str(move.account_id.parent_id.code)[0:2] == '13': for ad in bal: a = ad if 'AD' not in str(a[2]): saldo = {0: '', 1: '', 2: ''} bal.append(saldo) saldo = {0: 'Activo Fijo', 1: '', 2: ''} bal.append(saldo) saldo = {0: move.account_id.name, 1: balance, 2: 'AD'} # bal.append(saldo) elif str(move.account_id.parent_id.code)[0:2] == '21': if len(bal1) == 0: saldo = {0: '', 1: '', 2: ''} bal1.append(saldo) saldo = {0: 'Pasivo Corto Plazo', 1: '', 2: ''} bal1.append(saldo) saldo = { 0: move.account_id.name, 1: balance * -1, 2: 'PC' } elif str(move.account_id.parent_id.code)[0:2] == '22': for ad in bal1: a = ad if 'PO' not in str(a[2]): saldo = {0: '', 1: '', 2: ''} bal1.append(saldo) saldo = { 0: 'Pasivo Corto Plazo(Otros)', 1: '', 2: '' } bal1.append(saldo) saldo = { 0: move.account_id.name, 1: balance * -1, 2: 'PO' } elif str(move.account_id.parent_id.code)[0:2] == '25': for ad in bal1: a = ad if 'PL' not in str(a[2]): saldo = {0: '', 1: '', 2: ''} bal1.append(saldo) saldo = {0: 'Pasivo Largo Plazo', 1: '', 2: ''} bal1.append(saldo) saldo = { 0: move.account_id.name, 1: balance * -1, 2: 'PL' } elif str(move.account_id.parent_id.code)[0:1] == '3': for ad in bal1: a = ad if 'CT' not in str(a[2]): saldo = {0: '', 1: '', 2: ''} bal1.append(saldo) saldo = {0: 'Capital', 1: '', 2: ''} bal1.append(saldo) saldo = { 0: move.account_id.name, 1: balance * -1, 2: 'CT' } if 'AC' in str(saldo[2]) or 'AF' in str( saldo[2]) or 'AD' in str(saldo[2]): activo += saldo[1] bal.append(saldo) elif 'PC' in str(saldo[2]) or 'PO' in str( saldo[2]) or 'PL' in str(saldo[2]) or 'CT' in str( saldo[2]): pasivocapital += saldo[1] bal1.append(saldo) saldo = {0: 'Suma Activo', 1: activo, 2: ''} bal.append(saldo) saldo = {0: 'Suma Pasivo + Capital', 1: pasivocapital, 2: ''} bal1.append(saldo) #_________________________________________Consulta para sacar el reporte de Estado de resultados______________________________________________# elif reporte.reporte == 'est': ingresos = 0 egresos = 0 acc_ids = acc_obj.search(cr, uid, [('type', '!=', 'view')]) for cuenta in acc_obj.browse(cr, uid, acc_ids): balance = 0 acumuladoi = 0 acumuladoe = 0 if int(reporte.mes) < 10: mes = '0' + str(reporte.mes) + '/' + reporte.periodo.name else: mes = str(reporte.mes) + '/' + reporte.periodo.name period_obj = self.pool.get('account.period') #period_ids = period_obj.search(cr, uid, [('fiscalyear_id.name','=',reporte.periodo.name)]) period_mes = period_obj.search(cr, uid, [('code', '=', mes)]) for m in period_obj.browse(cr, uid, period_mes): month = m.id #if reporte.mensual == True: # move_ids = move_obj.search(cr, uid, [('period_id.fiscalyear_id.name','=',reporte.periodo.name),('account_id.id','=',cuenta.id),('period_id.code','=',mes)]) # move_acumulado = move_obj.search(cr, uid, [('period_id.fiscalyear_id.name','=',reporte.periodo.name),('account_id.id','=',cuenta.id),('period_id.id','<',month)]) #else: move_ids = move_obj.search(cr, uid, [('period_id.fiscalyear_id.name', '=', reporte.periodo.name), ('account_id.id', '=', cuenta.id)]) for move in move_obj.browse(cr, uid, move_ids): if reporte.mensual == True: if move.period_id.code == mes: balance += move.debit - move.credit #for move_a in move_obj.browse(cr, uid, move_acumulado): if str(move.account_id.parent_id.code)[0:1] == '5' or str( move.account_id.parent_id.code)[0:2] == '92': acumuladoi += move.debit - move.credit if str(move.account_id.parent_id.code)[0:1] == '6' or str( move.account_id.parent_id.code)[0:1] == '7' or str( move.account_id.parent_id.code )[0:1] == '8' or str( move.account_id.parent_id.code)[0:2] == '91': acumuladoe += move.debit - move.credit if round(balance, 2) != 0.0: if str(move.account_id.parent_id.code)[0:1] == '5' or str( move.account_id.parent_id.code)[0:2] == '92': if len(est) == 0: saldo = { 0: '', 1: '', 2: '', #3: '' } est.append(saldo) saldo = { 0: 'Ingresos', 1: '', 2: '', #3: '' } est.append(saldo) saldo = { 0: move.account_id.name, 1: balance, #2: acumuladoi, 2: 'I' } ingresos += balance est.append(saldo) if str(move.account_id.parent_id.code)[0:1] == '6' or str( move.account_id.parent_id.code)[0:1] == '7' or str( move.account_id.parent_id.code )[0:1] == '8' or str( move.account_id.parent_id.code)[0:2] == '91': for ad in est: a = ad if 'E' not in str(a[2]): saldo = { 0: 'Suma Ingresos', 1: ingresos, 2: '', #3: '' } est.append(saldo) saldo = { 0: '', 1: '', 2: '', #3: '' } est.append(saldo) saldo = { 0: 'Egresos', 1: '', 2: '', #3: '' } est.append(saldo) saldo = { 0: move.account_id.name, 1: balance, #2: acumuladoe, 2: 'E' } egresos += balance est.append(saldo) saldo = { 0: 'Suma Egresos', 1: egresos, 2: '', #3: '' } est.append(saldo) #__________________________________________________Variable de formato de consulta____________________________________________________________# com = {} if reporte.reporte == 'est': report = 'Estado de resultados' elif reporte.reporte == 'bal': report = 'Balance General' elif reporte.reporte == 'com': report = 'Balanza de comprobacion' if reporte.reporte == 'bal': com[0] = { 0: report + " " + reporte.periodo.name, 1: reporte.periodo.name, 2: company } elif reporte.reporte == 'est': com[0] = { 0: report + " " + self._get_mes(cr, uid, reporte.mes, context) + ' ' + reporte.periodo.name, 1: company } else: com[0] = { 0: report, 1: self._get_mes(cr, uid, reporte.mes, context), 2: reporte.periodo.name, 3: company } # #______________________________________________________Creacion del archivo PDF_______________________________________________________________# #______________________________________________________Creacion del archivo XLS_______________________________________________________________# libro = xlwt.Workbook() libro1 = libro.add_sheet("Consulta") book = xlwt.Workbook() sheet = book.add_sheet("Reporte") txt = "Fila %s, Columna %s" style = xlwt.XFStyle() # font font = xlwt.Font() font.bold = True style.font = font # borders borders = xlwt.Borders() borders.bottom = xlwt.Borders.DASHED style.borders = borders size = 48 im = Image.open(StringIO.StringIO(base64.b64decode(logo))) im.thumbnail(size, Image.ANTIALIAS) im.convert("RGB").save('tmp/logo.bmp') sheet.insert_bitmap('tmp/logo.bmp', 0, 0, 0, 0) # ) if reporte.reporte == 'bal': cabeceras = {0: 'Activo', 1: '-', 2: 'Pasivo'} for num in range(len(bal)): row = sheet.row(num) fila = bal[num] for col in range(0, 6): colunm = sheet.col(col) if col == 2: colunm.width = 32 * 30 else: colunm.width = 256 * 30 if num == 0: fila = com[num] for index, col in enumerate(fila): comp = com[0] if index == 0: row.write( index + 1, comp[col], xlwt.easyxf( "font: name Arial, height 280, color blue, bold on; align: wrap on, vert centre, horiz center" )) #pattern: pattern solid, fore_color white; row.height_mismatch = True row.height = 90 * 30 elif index == 2: row.write( index + 1, comp[col], xlwt.easyxf( "font: name Arial, height 280, color blue, bold on; align: wrap on, vert centre, horiz center" )) row.height_mismatch = True row.height = 90 * 30 else: for index, col in enumerate(fila): if num == 1: cab = cabeceras[index] if index == 1: cab = cabeceras[index + 1] row.write(index + 2, cab, style=style) elif index == 0: row.write(index, cab, style=style) elif num > 1: fila = bal[num - 2] celda = fila[index] #for index, col in enumerate(fila): #raise osv.except_osv(index, fila) if index < 2: if 'Activo' in str(celda): row.write(index, celda, style=style) else: row.write(index, celda) if num + 2 == len(bal): row = sheet.row(num + 2) for index, col in enumerate(fila): fila = bal[num] celda = fila[index] if index < 2: row.write(index, celda) if num + 1 == len(bal): row = sheet.row(num + 2) for index, col in enumerate(fila): fila = bal[num] celda = fila[index] row = sheet.row(32) if index < 2: if index == 0: row.write(index, celda, style=style) else: row.write(index, celda) for num in range(len(bal1)): row = sheet.row(num + 2) fila = bal1[num] for index, col in enumerate(fila): fila = bal1[num] celda = fila[index] if index < 2: if 'Suma' in str(fila[0]): row = sheet.row(32) if index == 0: row.write(index + 3, celda, style=style) else: row.write(index + 3, celda) elif 'Pasivo' in str(celda) or 'Capital' in str(celda): row.write(index + 3, celda, style=style) else: row.write(index + 3, celda) elif reporte.reporte == 'est': cabeceras = {0: 'Nombre', 1: 'Balance', 2: 'Acumulado'} for num in range(len(est)): row = sheet.row(num) fila = est[num] for col in range(0, 6): colunm = sheet.col(col) #if col == 2: # colunm.width = 32 * 30 #else: colunm.width = 256 * 30 if num == 0: fila = com[num] for index, col in enumerate(fila): comp = com[0] if index == 0: row.write( index + 1, comp[col], xlwt.easyxf( "font: name Arial, height 280, color blue, bold on; align: wrap on, vert centre, horiz center" )) #pattern: pattern solid, fore_color white; row.height_mismatch = True row.height = 90 * 30 elif index == 1: row.write( index + 1, comp[col], xlwt.easyxf( "font: name Arial, height 280, color blue, bold on; align: wrap on, vert centre, horiz center" )) row.height_mismatch = True row.height = 90 * 30 else: for index, col in enumerate(cabeceras): if num == 1: cab = cabeceras[index] #if index == 1: # cab = cabeceras[index+1] # row.write(index+2, cab, style=style) #elif index == 0: if index < 2: row.write(index, cab, style=style) elif num > 1: if index < 2: fila = est[num - 2] celda = fila[index] #for index, col in enumerate(fila): #raise osv.except_osv(index, fila) if index < 2: if 'Ingreso' in str(celda) or 'Egreso' in str( celda): row.write(index, celda, style=style) else: row.write(index, celda) if num + 2 == len(est): row = sheet.row(num + 2) for index, col in enumerate(fila): fila = est[num] celda = fila[index] if index < 2: row.write(index, celda) if num + 1 == len(est): row = sheet.row(num + 2) for index, col in enumerate(fila): fila = est[num] celda = fila[index] if index < 2: if index == 0: row.write(index, celda, style=style) else: row.write(index, celda) elif reporte.reporte == 'com': if reporte.mensual == True: for num in range(registros): row = sheet.row(num) fila = resultado[num] for col in range(0, 7): colunm = sheet.col(col) #if col == 2: # colunm.width = 32 * 30 #else: colunm.width = 256 * 30 if num == 0: fila = com[num] for index, col in enumerate(fila): comp = com[0] if index == 0: row.write( index + 1, comp[col], xlwt.easyxf( "font: name Arial, height 280, color blue, bold on; align: wrap on, vert centre, horiz center" ) ) #pattern: pattern solid, fore_color white; row.height_mismatch = True row.height = 90 * 30 elif index == 2: row.write( index + 1, comp[col], xlwt.easyxf( "font: name Arial, height 280, color blue, bold on; align: wrap on, vert centre, horiz center" )) row.height_mismatch = True row.height = 90 * 30 else: for index, col in enumerate(fila): if num == 1: cab = cabeceras[index] row.write(index, cab) #row.write(index, cab[0]) elif num > 1: fila = resultado[num - 2] celda = fila[index] row.write(index, celda) if num + 2 == registros: row = sheet.row(num + 2) for index, col in enumerate(fila): fila = resultado[num] celda = fila[index] row.write(index, celda) if num + 1 == registros: row = sheet.row(num + 2) for index, col in enumerate(fila): fila = resultado[num] celda = fila[index] row.write(index, celda) else: for num in range(registros): row = libro1.row(num) fila = resultado[num] if num == 0: fila = com[num] for index, col in enumerate(fila): colunm = libro1.col(col) colunm.width = 256 * 30 comp = com[0] row.write(index, comp[col]) else: for index, col in enumerate(fila): if num == 1: cab = cabeceras[index] row.write(index, cab) #row.write(index, cab[0]) elif num > 1: fila = resultado[num - 2] celda = fila[index] row.write(index, celda) if num + 2 == registros: row = libro1.row(num + 2) for index, col in enumerate(fila): fila = resultado[num] celda = fila[index] row.write(index, celda) if num + 1 == registros: row = libro1.row(num + 2) for index, col in enumerate(fila): fila = resultado[num] celda = fila[index] row.write(index, celda) # for num in range(len(bal1)): # row = sheet.row(num+2) # fila = bal1[num] # for index, col in enumerate(fila): # fila = bal1[num] # celda = fila[index] # if index < 2: # if 'Suma' in str(fila[0]): # row = sheet.row(32) # if index == 0: # row.write(index + 3, celda, style=style) # else: # row.write(index + 3, celda) # elif 'Pasivo' in str(celda) or 'Capital' in str(celda): # row.write(index + 3, celda, style=style) # else: # row.write(index+3, celda) fp = StringIO.StringIO() book.save(fp) fp.seek(0) data = fp.read() fp.close() out = base64.encodestring(data) book.save('tmp/Excel.pdf') this = self.browse(cr, uid, ids, context=context)[0] if 'Balance General' in report: filename = report + " " + reporte.periodo.name else: filename = report + " " + self._get_mes( cr, uid, reporte.mes, context) + " " + reporte.periodo.name extension = "xls" #this.format name = "%s.%s" % (filename, extension) this.write({'binario': out, 'name': name}) def _get_mes(self, cr, uid, mes, context=None): meses = [ 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre' ] mes_act = meses[int(mes) - 1] return mes_act _columns = { 'reporte': fields.selection([('bal', 'Balance General'), ('com', 'Balanza de comprobacion'), ('est', 'Estados de resultados')], 'Reporte', required=True, help="Escoger el informe a exportar"), 'nivel': fields.selection([('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6')], 'Nivel', help="Escoger el nivel", size=30), 'periodo': fields.many2one('account.fiscalyear', 'Periodo'), 'movimiento': fields.selection([('1', 'Todos los movimientos'), ('2', 'Todos los movimientos asentados')], 'Movimientos'), 'cero': fields.boolean( 'Cuentas cero', help="Marcar si se desea visualizar cuentas con saldo cero"), 'mensual': fields.boolean( 'Mensual', help="Marcar si se desea visualizar un mes en especifico"), 'mes': fields.selection([('1', 'Enero'), ('2', 'Febrero'), ('3', 'Marzo'), ('4', 'Abril'), ('5', 'Mayo'), ('6', 'Junio'), ('7', 'Julio'), ('8', 'Agosto'), ('9', 'Septiembre'), ('10', 'Octubre'), ('11', 'Noviembre'), ('12', 'Diciembre')], 'Mes', help="Escoger el mes"), 'todos': fields.boolean( 'Asientos', help="Marcar si se desea visualizar todos los asientos"), 'deb_cre': fields.boolean( 'Debito/Credito', help="Marcar si se desea visualizar la columna debito y credito"), #'archivo': fields.text('Archivo', size=30,help="Marcar si se desea visualizar un mes en especifico"), 'binario': fields.binary('Label', filters='*.xml', filename='Excel'), 'name': fields.char('File Name', readonly=True), #'bpdf': fields.binary('Label',filters='*.xml', filename='PDF'), #'namepdf': fields.char('File Name', readonly=True), } _defaults = { 'nivel': '1', 'periodo': '2', 'cero': False, 'mensual': True, 'mes': '1', 'todos': False, 'deb_cre': False, 'movimiento': '1', #'archivo': 'Excel.csv', #'binario': '/tmp/excel.csv', }
def onchange_logis_company(self, cr, uid, ids, logistic_company_id, context=None): res = {} if logistic_company_id: logistic_company = self.pool.get('logistic.company').browse(cr, uid, logistic_company_id, context=context) res = {'value': {'ship_company_code': logistic_company.ship_company_code,'sale_account_id':logistic_company.ship_account_id.id}} return res def _get_logis_company(self, cr, uid, context=None): if context is None: context = {} user_rec = self.pool.get('res.users').browse(cr ,uid, uid, context) logis_company = self.pool.get('logistic.company').search(cr, uid, []) return logis_company and logis_company[0] or False _columns= { 'logis_company': fields.many2one('logistic.company', 'Logistic Company', help='Name of the Logistics company providing the shipper services.'), 'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64), 'rate_selection': fields.selection([('rate_card', 'Rate Card'), ('rate_request', 'Rate Request')], 'Ship Rate Method'), 'partner_order_id': fields.many2one('res.partner', 'Ordering Contact', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The name and address of the contact who requested the order or quotation."), } _defaults = { 'partner_order_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').address_get(cr, uid, [context['partner_id']], ['order_contact'])['order_contact'], 'logis_company': _get_logis_company, } def onchange_partner_id(self, cr, uid, ids, part, context=None): addr = {} if part: addr = super(sale_order, self).onchange_partner_id(cr, uid, ids, part, context) addr['value'].update({'partner_order_id': part})
class sale_order(osv.Model): _inherit = 'sale.order' _columns = { 'carrier_id': fields.many2one( "delivery.carrier", string="Delivery Method", help= "Complete this field if you plan to invoice the shipping based on picking." ), } def onchange_partner_id(self, cr, uid, ids, part, context=None): result = super(sale_order, self).onchange_partner_id(cr, uid, ids, part, context=context) if part: dtype = self.pool.get('res.partner').browse( cr, uid, part, context=context).property_delivery_carrier.id # TDE NOTE: not sure the aded 'if dtype' is valid if dtype: result['value']['carrier_id'] = dtype return result def _delivery_unset(self, cr, uid, ids, context=None): sale_obj = self.pool['sale.order.line'] line_ids = sale_obj.search(cr, uid, [('order_id', 'in', ids), ('is_delivery', '=', True)], context=context) sale_obj.unlink(cr, uid, line_ids, context=context) def delivery_set(self, cr, uid, ids, context=None): line_obj = self.pool.get('sale.order.line') grid_obj = self.pool.get('delivery.grid') carrier_obj = self.pool.get('delivery.carrier') acc_fp_obj = self.pool.get('account.fiscal.position') self._delivery_unset(cr, uid, ids, context=context) currency_obj = self.pool.get('res.currency') line_ids = [] for order in self.browse(cr, uid, ids, context=context): grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id) if not grid_id: raise UserError(_('No grid matching for this carrier!')) if order.state not in ('draft', 'sent'): raise UserError( _('The order state have to be draft to add delivery lines.' )) grid = grid_obj.browse(cr, uid, grid_id, context=context) taxes = grid.carrier_id.product_id.taxes_id fpos = order.fiscal_position_id or False taxes_ids = acc_fp_obj.map_tax(cr, uid, fpos, taxes) price_unit = grid_obj.get_price(cr, uid, grid.id, order, time.strftime('%Y-%m-%d'), context) if order.company_id.currency_id.id != order.pricelist_id.currency_id.id: price_unit = currency_obj.compute( cr, uid, order.company_id.currency_id.id, order.pricelist_id.currency_id.id, price_unit, context=dict(context or {}, date=order.date_order)) #create the sale order line line_id = line_obj.create( cr, uid, { 'order_id': order.id, 'name': grid.carrier_id.name, 'product_uom_qty': 1, 'product_uom': grid.carrier_id.product_id.uom_id.id, 'product_id': grid.carrier_id.product_id.id, 'price_unit': price_unit, 'tax_id': [(6, 0, taxes_ids)], 'is_delivery': True }, context=context) line_ids.append(line_id) return line_ids
except UserError, e: # no suitable delivery method found, probably configuration error _logger.info("Carrier %s: %s", carrier.name, e.name) price = 0.0 else: price = 0.0 res[carrier.id] = { 'price': price, 'available': available } return res _columns = { 'name': fields.char('Delivery Method', required=True, translate=True), 'sequence': fields.integer('Sequence', help="Determine the display order"), 'partner_id': fields.many2one('res.partner', 'Transport Company', required=True, help="The partner that is doing the delivery service."), 'product_id': fields.many2one('product.product', 'Delivery Product', required=True), 'grids_id': fields.one2many('delivery.grid', 'carrier_id', 'Delivery Grids'), 'available' : fields.function(get_price, string='Available',type='boolean', multi='price', help="Is the carrier method possible with the current order."), 'price' : fields.function(get_price, string='Price', multi='price'), 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it."), 'normal_price': fields.float('Normal Price', help="Keep empty if the pricing depends on the advanced pricing per destination"), 'free_if_more_than': fields.boolean('Free If Order Total Amount Is More Than', help="If the order is more expensive than a certain amount, the customer can benefit from a free shipping"), 'amount': fields.float('Amount', help="Amount of the order to benefit from a free shipping, expressed in the company currency"), 'use_detailed_pricelist': fields.boolean('Advanced Pricing per Destination', help="Check this box if you want to manage delivery prices that depends on the destination, the weight, the total of the order, etc."), 'pricelist_ids': fields.one2many('delivery.grid', 'carrier_id', 'Advanced Pricing'), } _defaults = { 'active': 1,
class event_event(osv.osv): _inherit = "event.event" def _tz_get(self, cr, uid, context=None): # put POSIX 'Etc/*' entries at the end to avoid confusing users - see bug 1086728 return [(tz, tz) for tz in sorted(pytz.all_timezones, key=lambda tz: tz if not tz.startswith('Etc/') else '_')] def _count_tracks(self, cr, uid, ids, field_name, arg, context=None): return { event.id: len(event.track_ids) for event in self.browse(cr, uid, ids, context=context) } def _get_tracks_tag_ids(self, cr, uid, ids, field_names, arg=None, context=None): res = dict.fromkeys(ids, []) for event in self.browse(cr, uid, ids, context=context): for track in event.track_ids: res[event.id] += [tag.id for tag in track.tag_ids] res[event.id] = list(set(res[event.id])) return res _columns = { 'tag_ids': fields.many2many('event.tag', string='Tags'), 'track_ids': fields.one2many('event.track', 'event_id', 'Tracks'), 'sponsor_ids': fields.one2many('event.sponsor', 'event_id', 'Sponsorships'), 'blog_id': fields.many2one('blog.blog', 'Event Blog'), 'show_track_proposal': fields.boolean('Talks Proposals'), 'show_tracks': fields.boolean('Multiple Tracks'), 'show_blog': fields.boolean('News'), 'count_tracks': fields.function(_count_tracks, type='integer', string='Tracks'), 'tracks_tag_ids': fields.function(_get_tracks_tag_ids, type='one2many', relation='event.track.tag', string='Tags of Tracks'), 'allowed_track_tag_ids': fields.many2many('event.track.tag', string='Accepted Tags', help="List of available tags for track proposals."), 'timezone_of_event': fields.selection(_tz_get, 'Event Timezone', size=64), } _defaults = { 'show_track_proposal': False, 'show_tracks': False, 'show_blog': False, 'timezone_of_event': lambda self, cr, uid, c: self.pool.get('res.users').browse( cr, uid, uid, c).tz, } def _get_new_menu_pages(self, cr, uid, event, context=None): context = context or {} result = super(event_event, self)._get_new_menu_pages(cr, uid, event, context=context) if event.show_tracks: result.append((_('Talks'), '/event/%s/track' % slug(event))) result.append((_('Agenda'), '/event/%s/agenda' % slug(event))) if event.blog_id: result.append((_('News'), '/blogpost' + slug(event.blog_ig))) if event.show_track_proposal: result.append((_('Talk Proposals'), '/event/%s/track_proposal' % slug(event))) return result
def _get_icon_image(self, cr, uid, ids, field_name=None, arg=None, context=None): res = dict.fromkeys(ids, '') for module in self.browse(cr, uid, ids, context=context): path = addons.get_module_resource(module.name, 'static', 'src', 'img', 'icon.png') if path: image_file = tools.file_open(path, 'rb') try: res[module.id] = image_file.read().encode('base64') finally: image_file.close() return res _columns = { 'name': fields.char("Technical Name", size=128, readonly=True, required=True, select=True), 'category_id': fields.many2one('ir.module.category', 'Category', readonly=True, select=True), 'shortdesc': fields.char('Module Name', size=64, readonly=True, translate=True), 'summary': fields.char('Summary', size=64, readonly=True, translate=True), 'description': fields.text("Description", readonly=True, translate=True), 'description_html': fields.function(_get_desc, string='Description HTML', type='html', method=True, readonly=True), 'author': fields.char("Author", size=128, readonly=True), 'maintainer': fields.char('Maintainer', size=128, readonly=True), 'contributors': fields.text('Contributors', readonly=True), 'website': fields.char("Website", size=256, readonly=True), # attention: Incorrect field names !! # installed_version refers the latest version (the one on disk) # latest_version refers the installed version (the one in database) # published_version refers the version available on the repository 'installed_version': fields.function(_get_latest_version, string='Latest Version', type='char'), 'latest_version': fields.char('Installed Version', size=64, readonly=True),
class event_track(osv.osv): _name = "event.track" _description = 'Event Tracks' _order = 'priority, date' _inherit = ['mail.thread', 'ir.needaction_mixin', 'website.seo.metadata'] def _website_url(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, '') for track in self.browse(cr, uid, ids, context=context): res[track.id] = "/event/%s/track/%s" % (slug( track.event_id), slug(track)) return res _columns = { 'name': fields.char('Track Title', required=True, translate=True), 'user_id': fields.many2one('res.users', 'Responsible'), 'speaker_ids': fields.many2many('res.partner', string='Speakers'), 'tag_ids': fields.many2many('event.track.tag', string='Tags'), 'stage_id': fields.many2one('event.track.stage', 'Stage'), 'description': fields.html('Track Description', translate=True), 'date': fields.datetime('Track Date'), 'duration': fields.float('Duration', digits=(16, 2)), 'location_id': fields.many2one('event.track.location', 'Location'), 'event_id': fields.many2one('event.event', 'Event', required=True), 'color': fields.integer('Color Index'), 'priority': fields.selection([('3', 'Low'), ('2', 'Medium (*)'), ('1', 'High (**)'), ('0', 'Highest (***)')], 'Priority', required=True), 'website_published': fields.boolean('Available in the website'), 'website_url': fields.function(_website_url, string="Website url", type="char"), 'image': fields.related('speaker_ids', 'image', type='binary', readonly=True) } def set_priority(self, cr, uid, ids, priority, context={}): return self.write(cr, uid, ids, {'priority': priority}) def _default_stage_id(self, cr, uid, context={}): stage_obj = self.pool.get('event.track.stage') ids = stage_obj.search(cr, uid, [], context=context) return ids and ids[0] or False _defaults = { 'user_id': lambda self, cr, uid, ctx: uid, 'website_published': lambda self, cr, uid, ctx: False, 'duration': lambda *args: 1.5, 'stage_id': _default_stage_id, 'priority': '2' } def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None): stage_obj = self.pool.get('event.track.stage') result = stage_obj.name_search(cr, uid, '', context=context) return result, {} _group_by_full = { 'stage_id': _read_group_stage_ids, }
ACC_FISC_ALLOC_RULE_COLS_TMPL = { # Note: This are template style fields. # For nontemplate fields you might add aditional constraints to specific nontemplate fields (eg. company_id). # The chain method from itertools updates fields. Consider using this from within the nontemplate class when adding # new fields. # --- GENERAL SECTION --- 'name': fields.char('Name', required=True), 'description': fields.char('Description'), # This fiscal domain will narrow down the available fiscal attributes / fiscal allocations. # It should help clustering and reducing complexity. Rules are applied *additionally* # preserving the result (reed: taxes applied) of previous iterations. # However it is optional. You can construct more complex "cross-domain" rules leaving it empty. 'fiscal_domain_id': fields.many2one('account.fiscal.domain', 'Fiscal Domain', required=True, select=True), 'is_account_allocation': fields.boolean(u'Account Allocation?'), # --- CRITERION SECTION --- '{0}_country'.format(ATTR_USE_DOM_COMPANY[0]): fields.many2one('res.country', 'Country'), '{0}_state'.format(ATTR_USE_DOM_COMPANY[0]): fields.many2one( 'res.country.state', 'State', domain="[('country_id','=',{0}_country)]".format(ATTR_USE_DOM_COMPANY[0])), 'to_{0}_country'.format(ATTR_USE_DOM_PINVOICE[0]): fields.many2one( 'res.country', 'Country'), 'to_{0}_state'.format(ATTR_USE_DOM_PINVOICE[0]): fields.many2one( 'res.country.state', 'State', domain="[('country_id','=',to_{0}_country)]".format(ATTR_USE_DOM_PINVOICE[0])), 'to_{0}_country'.format(ATTR_USE_DOM_PSHIPPER[0]): fields.many2one( 'res.country', 'Country'),
clock_ids = self.pool.get("hr.clock").search(cr, uid, [], context=context) clock_ids_exist = [] try: for order in self.browse(cr, uid, ids, context=context): emp_code = order.employee_id.emp_code for clock_id in clock_ids: emps_clock = clock_sync_obj.clock_emps_get(cr, uid, clock_id, [emp_code], context=context) if emps_clock: clock_ids_exist.append(clock_id) resu[order.id] = clock_ids_exist except Exception,e: traceback.print_exc() pass return resu _columns = { 'employee_id': fields.many2one('hr.employee', 'Employee', required=True, select=True), 'department_id':fields.related('employee_id','department_id', type='many2one', relation='hr.department', string='Department', store=True), 'job_id':fields.related('employee_id','job_id', type='many2one', relation='hr.job', string='Title', store=True), 'emp_code':fields.related('employee_id','emp_code', type='char', string='Employee Code', store=True), 'mobile_phone':fields.related('employee_id','mobile_phone', type='char', string='Work Mobile', store=True), 'borrow_money_residual':fields.related('employee_id','money_residual', type='float', string='Borrowed residual', readonly=True), 'dimmission_reason':fields.text('Dimission Reason', required=True), 'advice_to_company':fields.text('Advice to company'), 'employment_start':fields.date('Employment Started'), 'date_request':fields.date('Request Date', required=True), 'date_done':fields.date('Done Date', required=False, readonly=True), 'approve_ids': fields.one2many('hr.dimission.item', 'dimission_id', 'Approvals', domain=[('type','=','approve')]), 'transfer_ids': fields.one2many('hr.dimission.item', 'dimission_id', 'Transfers', domain=[('type','=','transfer')]),
return self.write(cr, uid, id, {"file_db_store": value}, context=context) _columns = { "name": fields.char("Image Title", size=64), "filename": fields.char("Filename", size=64), "extension": fields.char("file extension", oldname="extention"), "link": fields.boolean( "Link?", help="Images can be linked from files on " "your file system or remote (Preferred)" ), "file_db_store": fields.binary("Image stored in database"), "file": fields.function( _get_image, fnct_inv=_set_image, type="binary", string="File", filters="*.png,*.jpg,*.gif" ), "url": fields.char("File Location"), "url_big": fields.char("File Location Image Size Big"), "url_medium": fields.char("File Location Image Size Medium"), "url_small": fields.char("File Location Image Size Small"), "comments": fields.text("Comments"), "product_id": fields.many2one("product.product", "Product"), } _defaults = {"link": True} _sql_constraints = [ ( "uniq_name_product_id", "UNIQUE(product_id, name)", _("A product can have only one " "image with the same name"), ) ]
class sale_order(osv.osv): _inherit = "sale.order" def copy(self, cr, uid, id, default=None, context=None): if not default: default = {} default.update({ 'shipped': False, 'picking_ids': [], }) return super(sale_order, self).copy(cr, uid, id, default, context=context) def shipping_policy_change(self, cr, uid, ids, policy, context=None): if not policy: return {} inv_qty = 'order' if policy == 'prepaid': inv_qty = 'order' elif policy == 'picking': inv_qty = 'procurement' return {'value': {'invoice_quantity': inv_qty}} def write(self, cr, uid, ids, vals, context=None): if vals.get('order_policy', False): if vals['order_policy'] == 'prepaid': vals.update({'invoice_quantity': 'order'}) elif vals['order_policy'] == 'picking': vals.update({'invoice_quantity': 'procurement'}) return super(sale_order, self).write(cr, uid, ids, vals, context=context) def create(self, cr, uid, vals, context=None): if vals.get('order_policy', False): if vals['order_policy'] == 'prepaid': vals.update({'invoice_quantity': 'order'}) if vals['order_policy'] == 'picking': vals.update({'invoice_quantity': 'procurement'}) order = super(sale_order, self).create(cr, uid, vals, context=context) return order # This is False def _picked_rate(self, cr, uid, ids, name, arg, context=None): if not ids: return {} res = {} tmp = {} for id in ids: tmp[id] = {'picked': 0.0, 'total': 0.0} cr.execute('''SELECT p.sale_id as sale_order_id, sum(m.product_qty) as nbr, mp.state as procurement_state, m.state as move_state, p.type as picking_type FROM stock_move m LEFT JOIN stock_picking p on (p.id=m.picking_id) LEFT JOIN procurement_order mp on (mp.move_id=m.id) WHERE p.sale_id IN %s GROUP BY m.state, mp.state, p.sale_id, p.type''', (tuple(ids),)) for item in cr.dictfetchall(): if item['move_state'] == 'cancel': continue if item['picking_type'] == 'in':#this is a returned picking tmp[item['sale_order_id']]['total'] -= item['nbr'] or 0.0 # Deducting the return picking qty if item['procurement_state'] == 'done' or item['move_state'] == 'done': tmp[item['sale_order_id']]['picked'] -= item['nbr'] or 0.0 else: tmp[item['sale_order_id']]['total'] += item['nbr'] or 0.0 if item['procurement_state'] == 'done' or item['move_state'] == 'done': tmp[item['sale_order_id']]['picked'] += item['nbr'] or 0.0 for order in self.browse(cr, uid, ids, context=context): if order.shipped: res[order.id] = 100.0 else: res[order.id] = tmp[order.id]['total'] and (100.0 * tmp[order.id]['picked'] / tmp[order.id]['total']) or 0.0 return res _columns = { 'state': fields.selection([ ('draft', 'Draft Quotation'), ('sent', 'Quotation Sent'), ('cancel', 'Cancelled'), ('waiting_date', 'Waiting Schedule'), ('progress', 'Sales Order'), ('manual', 'Sale to Invoice'), ('shipping_except', 'Shipping Exception'), ('invoice_except', 'Invoice Exception'), ('done', 'Done'), ], 'Status', readonly=True,help="Gives the status of the quotation or sales order.\ \nThe exception status is automatically set when a cancel operation occurs \ in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception).\nThe 'Waiting Schedule' status is set when the invoice is confirmed\ but waiting for the scheduler to run on the order date.", select=True), 'incoterm': fields.many2one('stock.incoterms', 'Incoterm', help="International Commercial Terms are a series of predefined commercial terms used in international transactions."), 'picking_policy': fields.selection([('direct', 'Deliver each product when available'), ('one', 'Deliver all products at once')], 'Shipping Policy', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="""Pick 'Deliver each product when available' if you allow partial delivery."""), 'order_policy': fields.selection([ ('manual', 'On Demand'), ('picking', 'On Delivery Order'), ('prepaid', 'Before Delivery'), ], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="""On demand: A draft invoice can be created from the sales order when needed. \nOn delivery order: A draft invoice can be created from the delivery order when the products have been delivered. \nBefore delivery: A draft invoice is created from the sales order and must be paid before the products can be delivered."""), 'picking_ids': fields.one2many('stock.picking.out', 'sale_id', 'Related Picking', readonly=True, help="This is a list of delivery orders that has been generated for this sales order."), 'shipped': fields.boolean('Delivered', readonly=True, help="It indicates that the sales order has been delivered. This field is updated only after the scheduler(s) have been launched."), 'picked_rate': fields.function(_picked_rate, string='Picked', type='float'), 'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on', help="The sales order will automatically create the invoice proposition (draft invoice).\ You have to choose if you want your invoice based on ordered ", required=True, readonly=True, states={'draft': [('readonly', False)]}), } _defaults = { 'picking_policy': 'direct', 'order_policy': 'manual', 'invoice_quantity': 'order', } # Form filling def unlink(self, cr, uid, ids, context=None): sale_orders = self.read(cr, uid, ids, ['state'], context=context) unlink_ids = [] for s in sale_orders: if s['state'] in ['draft', 'cancel']: unlink_ids.append(s['id']) else: raise osv.except_osv(_('Invalid Action!'), _('In order to delete a confirmed sales order, you must cancel it.\nTo do so, you must first cancel related picking for delivery orders.')) return osv.osv.unlink(self, cr, uid, unlink_ids, context=context) def action_view_delivery(self, cr, uid, ids, context=None): ''' This function returns an action that display existing delivery orders of given sales order ids. It can either be a in a list or in a form view, if there is only one delivery order to show. ''' mod_obj = self.pool.get('ir.model.data') act_obj = self.pool.get('ir.actions.act_window') result = mod_obj.get_object_reference(cr, uid, 'stock', 'action_picking_tree') id = result and result[1] or False result = act_obj.read(cr, uid, [id], context=context)[0] #compute the number of delivery orders to display pick_ids = [] for so in self.browse(cr, uid, ids, context=context): pick_ids += [picking.id for picking in so.picking_ids] #choose the view_mode accordingly if len(pick_ids) > 1: result['domain'] = "[('id','in',["+','.join(map(str, pick_ids))+"])]" else: res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_form') result['views'] = [(res and res[1] or False, 'form')] result['res_id'] = pick_ids and pick_ids[0] or False return result def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_invoice = False, context=None): picking_obj = self.pool.get('stock.picking') res = super(sale_order,self).action_invoice_create( cr, uid, ids, grouped=grouped, states=states, date_invoice = date_invoice, context=context) for order in self.browse(cr, uid, ids, context=context): if order.order_policy == 'picking': picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'}) return res def action_cancel(self, cr, uid, ids, context=None): wf_service = netsvc.LocalService("workflow") if context is None: context = {} sale_order_line_obj = self.pool.get('sale.order.line') proc_obj = self.pool.get('procurement.order') for sale in self.browse(cr, uid, ids, context=context): for pick in sale.picking_ids: if pick.state not in ('draft', 'cancel'): raise osv.except_osv( _('Cannot cancel sales order!'), _('You must first cancel all delivery order(s) attached to this sales order.')) if pick.state == 'cancel': for mov in pick.move_lines: proc_ids = proc_obj.search(cr, uid, [('move_id', '=', mov.id)]) if proc_ids: for proc in proc_ids: wf_service.trg_validate(uid, 'procurement.order', proc, 'button_check', cr) for r in self.read(cr, uid, ids, ['picking_ids']): for pick in r['picking_ids']: wf_service.trg_validate(uid, 'stock.picking', pick, 'button_cancel', cr) return super(sale_order, self).action_cancel(cr, uid, ids, context=context) def action_wait(self, cr, uid, ids, context=None): res = super(sale_order, self).action_wait(cr, uid, ids, context=context) for o in self.browse(cr, uid, ids): noprod = self.test_no_product(cr, uid, o, context) if noprod and o.order_policy=='picking': self.write(cr, uid, [o.id], {'order_policy': 'manual'}, context=context) return res def procurement_lines_get(self, cr, uid, ids, *args): res = [] for order in self.browse(cr, uid, ids, context={}): for line in order.order_line: if line.procurement_id: res.append(line.procurement_id.id) return res def date_to_datetime(self, cr, uid, userdate, context=None): """ Convert date values expressed in user's timezone to server-side UTC timestamp, assuming a default arbitrary time of 12:00 AM - because a time is needed. :param str userdate: date string in in user time zone :return: UTC datetime string for server-side use """ # TODO: move to fields.datetime in server after 7.0 user_date = datetime.strptime(userdate, DEFAULT_SERVER_DATE_FORMAT) if context and context.get('tz'): tz_name = context['tz'] else: tz_name = self.pool.get('res.users').read(cr, SUPERUSER_ID, uid, ['tz'])['tz'] if tz_name: utc = pytz.timezone('UTC') context_tz = pytz.timezone(tz_name) user_datetime = user_date + relativedelta(hours=12.0) local_timestamp = context_tz.localize(user_datetime, is_dst=False) user_datetime = local_timestamp.astimezone(utc) return user_datetime.strftime(DEFAULT_SERVER_DATETIME_FORMAT) return user_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT) # if mode == 'finished': # returns True if all lines are done, False otherwise # if mode == 'canceled': # returns True if there is at least one canceled line, False otherwise def test_state(self, cr, uid, ids, mode, *args): assert mode in ('finished', 'canceled'), _("invalid mode for test_state") finished = True canceled = False write_done_ids = [] write_cancel_ids = [] for order in self.browse(cr, uid, ids, context={}): for line in order.order_line: if (not line.procurement_id) or (line.procurement_id.state=='done'): if line.state != 'done': write_done_ids.append(line.id) else: finished = False if line.procurement_id: if (line.procurement_id.state == 'cancel'): canceled = True if line.state != 'exception': write_cancel_ids.append(line.id) if write_done_ids: self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'}) if write_cancel_ids: self.pool.get('sale.order.line').write(cr, uid, write_cancel_ids, {'state': 'exception'}) if mode == 'finished': return finished elif mode == 'canceled': return canceled def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None): return { 'name': line.name, 'origin': order.name, 'date_planned': date_planned, 'product_id': line.product_id.id, 'product_qty': line.product_uom_qty, 'product_uom': line.product_uom.id, 'product_uos_qty': (line.product_uos and line.product_uos_qty)\ or line.product_uom_qty, 'product_uos': (line.product_uos and line.product_uos.id)\ or line.product_uom.id, 'location_id': order.shop_id.warehouse_id.lot_stock_id.id, 'procure_method': line.type, 'move_id': move_id, 'company_id': order.company_id.id, 'note': line.name, 'property_ids': [(6, 0, [x.id for x in line.property_ids])], } def _prepare_order_line_move(self, cr, uid, order, line, picking_id, date_planned, context=None): location_id = order.shop_id.warehouse_id.lot_stock_id.id output_id = order.shop_id.warehouse_id.lot_output_id.id return { 'name': line.name, 'picking_id': picking_id, 'product_id': line.product_id.id, 'date': date_planned, 'date_expected': date_planned, 'product_qty': line.product_uom_qty, 'product_uom': line.product_uom.id, 'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty, 'product_uos': (line.product_uos and line.product_uos.id)\ or line.product_uom.id, 'product_packaging': line.product_packaging.id, 'partner_id': line.address_allotment_id.id or order.partner_shipping_id.id, 'location_id': location_id, 'location_dest_id': output_id, 'sale_line_id': line.id, 'tracking_id': False, 'state': 'draft', #'state': 'waiting', 'company_id': order.company_id.id, 'price_unit': line.product_id.standard_price or 0.0 } def _prepare_order_picking(self, cr, uid, order, context=None): pick_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.out') return { 'name': pick_name, 'origin': order.name, 'date': self.date_to_datetime(cr, uid, order.date_order, context), 'type': 'out', 'state': 'auto', 'move_type': order.picking_policy, 'sale_id': order.id, 'partner_id': order.partner_shipping_id.id, 'note': order.note, 'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none', 'company_id': order.company_id.id, } def ship_recreate(self, cr, uid, order, line, move_id, proc_id): # FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot) """ Define ship_recreate for process after shipping exception param order: sales order to which the order lines belong param line: sales order line records to procure param move_id: the ID of stock move param proc_id: the ID of procurement """ move_obj = self.pool.get('stock.move') if order.state == 'shipping_except': for pick in order.picking_ids: for move in pick.move_lines: if move.state == 'cancel': mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)]) if mov_ids: for mov in move_obj.browse(cr, uid, mov_ids): # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum? move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty}) self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty}) return True def _get_date_planned(self, cr, uid, order, line, start_date, context=None): start_date = self.date_to_datetime(cr, uid, start_date, context) date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=line.delay or 0.0) date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) return date_planned def _create_pickings_and_procurements(self, cr, uid, order, order_lines, picking_id=False, context=None): """Create the required procurements to supply sales order lines, also connecting the procurements to appropriate stock moves in order to bring the goods to the sales order's requested location. If ``picking_id`` is provided, the stock moves will be added to it, otherwise a standard outgoing picking will be created to wrap the stock moves, as returned by :meth:`~._prepare_order_picking`. Modules that wish to customize the procurements or partition the stock moves over multiple stock pickings may override this method and call ``super()`` with different subsets of ``order_lines`` and/or preset ``picking_id`` values. :param browse_record order: sales order to which the order lines belong :param list(browse_record) order_lines: sales order line records to procure :param int picking_id: optional ID of a stock picking to which the created stock moves will be added. A new picking will be created if ommitted. :return: True """ move_obj = self.pool.get('stock.move') picking_obj = self.pool.get('stock.picking') procurement_obj = self.pool.get('procurement.order') proc_ids = [] for line in order_lines: if line.state == 'done': continue date_planned = self._get_date_planned(cr, uid, order, line, order.date_order, context=context) if line.product_id: if line.product_id.type in ('product', 'consu'): if not picking_id: picking_id = picking_obj.create(cr, uid, self._prepare_order_picking(cr, uid, order, context=context)) move_id = move_obj.create(cr, uid, self._prepare_order_line_move(cr, uid, order, line, picking_id, date_planned, context=context)) else: # a service has no stock move move_id = False proc_id = procurement_obj.create(cr, uid, self._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, context=context)) proc_ids.append(proc_id) line.write({'procurement_id': proc_id}) self.ship_recreate(cr, uid, order, line, move_id, proc_id) wf_service = netsvc.LocalService("workflow") if picking_id: wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr) for proc_id in proc_ids: wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr) val = {} if order.state == 'shipping_except': val['state'] = 'progress' val['shipped'] = False if (order.order_policy == 'manual'): for line in order.order_line: if (not line.invoiced) and (line.state not in ('cancel', 'draft')): val['state'] = 'manual' break order.write(val) return True def action_ship_create(self, cr, uid, ids, context=None): for order in self.browse(cr, uid, ids, context=context): self._create_pickings_and_procurements(cr, uid, order, order.order_line, None, context=context) return True def action_ship_end(self, cr, uid, ids, context=None): for order in self.browse(cr, uid, ids, context=context): val = {'shipped': True} if order.state == 'shipping_except': val['state'] = 'progress' if (order.order_policy == 'manual'): for line in order.order_line: if (not line.invoiced) and (line.state not in ('cancel', 'draft')): val['state'] = 'manual' break for line in order.order_line: towrite = [] if line.state == 'exception': towrite.append(line.id) if towrite: self.pool.get('sale.order.line').write(cr, uid, towrite, {'state': 'done'}, context=context) res = self.write(cr, uid, [order.id], val) return True def has_stockable_products(self, cr, uid, ids, *args): for order in self.browse(cr, uid, ids): for order_line in order.order_line: if order_line.product_id and order_line.product_id.type in ('product', 'consu'): return True return False