diff --git a/library_management/.gitignore b/library_management/.gitignore
new file mode 100644
index 000000000..ba7466050
--- /dev/null
+++ b/library_management/.gitignore
@@ -0,0 +1,57 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
diff --git a/library_management/__init__.py b/library_management/__init__.py
new file mode 100644
index 000000000..5af2e594d
--- /dev/null
+++ b/library_management/__init__.py
@@ -0,0 +1,4 @@
+import library
+import registration
+import report
+import res_config
diff --git a/library_management/__openerp__.py b/library_management/__openerp__.py
new file mode 100644
index 000000000..5623f3115
--- /dev/null
+++ b/library_management/__openerp__.py
@@ -0,0 +1,30 @@
+{
+ 'name': 'Public Library Management ',
+ 'version': '1.0',
+ 'author' : 'Cybrosys',
+ 'category': 'Tools',
+ 'summary': 'book management',
+ 'description': """
+Public Library Management
+================================
+Module to manage library.
+ Books Information,
+ Publisher and Author Information,
+ Book Rack Tracking etc...
+""",
+ 'depends' : ['base', 'sale', 'report_intrastat', 'stock', 'mail', 'account', 'account_accountant'],
+ 'data' : [
+ 'view/registration.xml',
+ 'view/library.xml',
+ 'view/user_view.xml',
+ 'res_config_view.xml',
+ 'view/report_invoice.xml',
+ 'report.xml',
+ 'security/ir.model.access.csv',
+ 'demo.xml',
+ ],
+ 'images': [],
+ 'demo': [],
+ 'installable' : True,
+ 'application': True,
+}
diff --git a/library_management/demo.xml b/library_management/demo.xml
new file mode 100644
index 000000000..fd41732f6
--- /dev/null
+++ b/library_management/demo.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ 10
+ 5
+
+
+
+
+
+
+
+
diff --git a/library_management/library.py b/library_management/library.py
new file mode 100644
index 000000000..d24e0865d
--- /dev/null
+++ b/library_management/library.py
@@ -0,0 +1,772 @@
+from openerp import models, fields, tools, api
+from openerp.tools.translate import _
+from datetime import datetime, timedelta, date
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, image_colorize, image_resize_image_big
+import openerp
+from openerp.exceptions import Warning
+
+
+class library_rack(models.Model):
+ _name = 'library.rack'
+ code = fields.Char(string='Code', size=64, required=True, readonly=True,
+ help="it will be show the position of book")
+ name = fields.Char(string='Name', size=16)
+ active = fields.Boolean('Active', default=True)
+ book_ids = fields.One2many('product.product', compute='compute_book')
+ _sql_constraints = [('code.unique', 'unique(code)', 'The code of the rack must be unique !!'),
+ ('name_uniq', 'unique (name)', 'The name of rack already exists !!')]
+ _defaults = {'code': lambda self, cr, uid, context: 'rack'}
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('code', _('rack')) == _('rack'):
+ values['code'] = self.pool.get('ir.sequence').get(cr, uid, 'library.rack')
+ return super(library_rack, self).create(cr, uid, values, context=context)
+
+ def compute_book(self):
+ book_obj = self.pool.get('product.product')
+ browse = self.browse(self._ids)
+ student_ids = book_obj.search(self._cr, self._uid, [('rack', '=', browse.name)])
+ self.book_ids = student_ids
+
+
+class product_lang(models.Model):
+ _name = 'product.lang'
+ code = fields.Char('Code', size=4, required=True, readonly=True)
+ name = fields.Char('Name', size=128, required=True)
+ book_ids = fields.One2many('product.product', compute='compute_book')
+ _sql_constraints = [('name_uniq', 'unique (name)', 'The name of the language must be unique !'),
+ ('code_uniq', 'unique (code)', 'The code of the lang must be unique !')]
+
+ _defaults = {
+ 'code': lambda self, cr, uid, context: 'language'
+ }
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('code', _('language')) == _('language'):
+ values['code'] = self.pool.get('ir.sequence').get(cr, uid, 'product.lang')
+ return super(product_lang, self).create(cr, uid, values, context=context)
+
+ def compute_book(self):
+ book_obj = self.pool.get('product.product')
+ browse = self.browse(self._ids)
+ student_ids = book_obj.search(self._cr, self._uid, [('lang', '=', browse.name)])
+ self.book_ids = student_ids
+
+
+class library_book_returnday(models.Model):
+ _name = 'library.book.returnday'
+ _rec_name = 'day'
+ day = fields.Integer('Days', default=1, required=True, help="It show the no of day/s for returning book")
+ code = fields.Char('Code', readonly=True, size=16)
+ fine_amt = fields.Float('Fine Amount', default=1, required=True,
+ help="Fine amount to be paid after due of book return date")
+ _sql_constraints = [('name_uniq', 'unique (code)', 'The code of the return days must be unique !')]
+ _defaults = {'code': lambda self, cr, uid, context: 'day'}
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('code', _('day')) == _('day'):
+ values['code'] = self.pool.get('ir.sequence').get(cr, uid, 'library.book.returnday')
+ return super(library_book_returnday, self).create(cr, uid, values, context=context)
+
+
+class library_price_category(models.Model):
+ _name = 'library.price.category'
+ _description = 'Book Category'
+
+ name = fields.Char('Category', size=64, required=True)
+ code = fields.Char('Code', readonly=True)
+ book_ids = fields.One2many('product.product', compute='compute_book')
+ _sql_constraints = [('name_uniq', 'unique (code)', 'The code of the category must be unique !')]
+ _defaults = {'code': lambda self, cr, uid, context: 'category'}
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('code', _('category')) == _('category'):
+ values['code'] = self.pool.get('ir.sequence').get(cr, uid, 'library.price.cat')
+ return super(library_price_category, self).create(cr, uid, values, context=context)
+
+ def compute_book(self):
+ book_obj = self.pool.get('product.product')
+ browse = self.browse(self._ids)
+ student_ids = book_obj.search(self._cr, self._uid, [('book_cat', '=', browse.name)])
+ self.book_ids = student_ids
+
+
+class stock_change_quantity(models.Model):
+ _inherit = "stock.change.product.qty"
+
+ def change_product_qty(self, cr, uid, ids, context=None):
+ conf = self.pool.get('ir.values')
+ store_conf = conf.get_default(cr, uid, 'library.config.settings', 'store')
+ ware_brow = self.pool.get('stock.warehouse').browse(cr, uid, store_conf, context=context)
+ if store_conf == False or store_conf == None:
+ raise Warning(_("Warning"), _("Set a store to library from Library settings"))
+ get_conf_store = ware_brow.code
+ if context is None:
+ context = {}
+ inventory_obj = self.pool.get('stock.inventory')
+ inventory_line_obj = self.pool.get('stock.inventory.line')
+ po_id = context.get('active_id')
+ prod_obj = self.pool.get('product.product')
+ prod = prod_obj.browse(cr, uid, po_id, context=context)
+ for data in self.browse(cr, uid, ids, context=context):
+ get_trans_loc = data.location_id.location_id.name
+ if get_conf_store == get_trans_loc:
+ prod_obj.write(cr, uid, po_id, {'total_copies': data.new_quantity,
+ 'available_copies': data.new_quantity})
+ if data.new_quantity < 0:
+ raise Warning(_("Warning"), _("Quantity cannot be negative."))
+ ctx = context.copy()
+ ctx['location'] = data.location_id.id
+ ctx['lot_id'] = data.lot_id.id
+ if data.product_id.id and data.lot_id.id:
+ filter = 'none'
+ elif data.product_id.id:
+ filter = 'product'
+ else:
+ filter = 'none'
+ inventory_id = inventory_obj.create(cr, uid, {
+ 'name': _('INV: %s') % tools.ustr(data.product_id.name),
+ 'filter': filter,
+ 'product_id': data.product_id.id,
+ 'location_id': data.location_id.id,
+ 'lot_id': data.lot_id.id}, context=context)
+ product = data.product_id.with_context(location=data.location_id.id, lot_id=data.lot_id.id)
+ th_qty = product.qty_available
+ line_data = {
+ 'inventory_id': inventory_id,
+ 'product_qty': data.new_quantity,
+ 'location_id': data.location_id.id,
+ 'product_id': data.product_id.id,
+ 'product_uom_id': data.product_id.uom_id.id,
+ 'theoretical_qty': th_qty,
+ 'prod_lot_id': data.lot_id.id
+ }
+ inventory_line_obj.create(cr, uid, line_data, context=context)
+ inventory_obj.action_done(cr, uid, [inventory_id], context=context)
+ return {}
+
+
+class library_book_issue(models.Model):
+ _name = 'library.book.issue'
+ _description = "Library information"
+ name = fields.Many2one('product.product', 'Book Name', required=True)
+ issue_code = fields.Char('Issue No.', size=24, required=True, readonly=True, copy=False)
+ user = fields.Many2one('res.partner', 'User Name')
+ invoice_id = fields.Many2one('account.invoice', "User's Invoice")
+ date_issue = fields.Datetime('Release Date', readonly=True, default=datetime.now(),
+ help="Release(Issue) date of the book")
+ date_return = fields.Datetime(string='Return Date', readonly=True,
+ help="Book To Be Return On This Date", copy=False)
+ actual_return_date = fields.Datetime("Actual Return Date", readonly=True, help="Actual Return Date of Book")
+ penalty = fields.Float(string='Penalty For Late Book Return',
+ help='It show the late book return penalty', readonly=True)
+ lost_penalty = fields.Float(string='Fine', help='It show the penalty for lost book')
+ day_to_return_book = fields.Many2one("library.book.returnday", "Book Return Days", copy=False)
+ card_id = fields.Many2one("library.card", "Card No", required=True)
+ state = fields.Selection([('draft', 'Draft'), ('issue', 'Issued'), ('transfered', 'Transfered'),
+ ('reissue', 'Reissued'), ('cancel', 'Cancelled'), ('lost', 'Lost'),
+ ('return', 'Returned'), ('paid', 'Paid')], "State")
+
+ color = fields.Integer("Color Index")
+ _defaults = {
+ 'state': 'draft',
+ 'issue_code': lambda self, cr, uid, context: 'issue'
+ }
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('issue_code', _('issue')) == _('issue'):
+ values['issue_code'] = self.pool.get('ir.sequence').get(cr, uid, 'library.book.issue')
+ return super(library_book_issue, self).create(cr, uid, values, context=context)
+
+ @api.multi
+ def invoice_print(self):
+ return self.env['report'].get_action(self, 'library_management.report_invoice_library')
+
+ def _library_reminder(self, cr, uid, context=None):
+ tommarrow = datetime.now() + timedelta(days=1)
+ issue_obj = self.pool.get('library.book.issue')
+ late_ids = issue_obj.search(cr, uid, [('state', '=', 'transfered')])
+ for i in late_ids:
+ a = issue_obj.browse(cr, uid, i, context)
+ date_return = datetime.strptime(a.date_return, DEFAULT_SERVER_DATETIME_FORMAT)
+ if tommarrow.date() == date_return.date():
+ post_vars = {'subject': "Library- Reminder",
+ 'body': "Hello " + str(a.user.name) + ", Your book(" + str(a.name.name) +
+ ") return date is tommarrow" + "(" + str(date_return.date()) + ")" +
+ ". Please try to return the book as soon as possible. Else You need to pay the fine.",
+ 'model': 'library.book.issue',
+ 'partner_ids': [a.user.id]}
+ thread_pool = self.pool.get('mail.thread')
+ thread_pool.message_post(cr, uid, False, type="comment", subtype="mt_comment",
+ context=context, **post_vars)
+
+ def transfer_book(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids):
+ conf = self.pool.get('ir.values')
+ store_conf = conf.get_default(cr, uid, 'library.config.settings', 'store')
+ ware_brow = self.pool.get('stock.warehouse').browse(cr, uid, store_conf, context=context)
+ if store_conf == False or store_conf == None:
+ raise Warning(_("Warning"), _("Set a store to library from Library settings"))
+ product_rec = self.pool.get('product.product').browse(cr, uid, order.name.id, context=context)
+ book = product_rec.name
+ uom_id = product_rec.uom_id
+ searc = self.pool.get('product.product').search(cr, uid, [('product_tmpl_id', '=', book)])
+ whstocks = self.pool.get('stock.location').search(cr, uid, [('location_id.name', '=', ware_brow.code),
+ ('name', '=', 'Stock')], context=context)
+ whstock = whstocks[0]
+ whsto = self.pool.get('stock.location').browse(cr, uid, whstock, context=None)
+ search_picks = self.pool.get('stock.picking.type'). \
+ search(cr, uid, [('warehouse_id.name', '=', ware_brow.name)], context=context)
+ search_pick = search_picks[2]
+ picking_vals = {
+ 'picking_type_id': search_pick,
+ 'partner_id': order.user.id,
+ 'date': date.today(),
+ 'origin': order.issue_code,
+ }
+
+ picking_id = self.pool.get('stock.picking').create(cr, uid, picking_vals, context=context)
+ vals = {
+ 'name': order.id or '',
+ 'product_id': searc[0],
+ 'product_uom': uom_id.id,
+ 'date': date.today(),
+ 'location_id': whsto.id,
+ 'location_dest_id': order.user.property_stock_customer.id,
+ 'picking_id': picking_id,
+ }
+ move_id = self.pool.get('stock.move').create(cr, uid, vals, context=context)
+ self.pool.get('stock.move').force_assign(cr, uid, [move_id], context=context)
+ return {
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'stock.picking',
+ 'context': context,
+ 'type': 'ir.actions.act_window',
+ 'res_id': picking_id
+ }
+
+ def issue_book(self, cr, uid, ids, context=None):
+ product_obj = self.pool.get('product.product')
+ for issue in self.browse(cr, uid, ids, context=context):
+ card_ids = self.search(cr, uid, [('card_id', '=', issue.card_id.id),
+ ('state', 'in', ['issue', 'reissue', 'transfered'])])
+ if issue.card_id.book_limit > len(card_ids) and issue.name.available_copies > 0:
+ self.write(cr, uid, ids, {'state': 'issue', 'date_issue': datetime.now()}, context=context)
+ elif issue.card_id.book_limit <= len(card_ids) and issue.name.available_copies > 0:
+ raise Warning(_("Warning"), _("Exceeded maximum book limit..."))
+ elif issue.card_id.book_limit > len(card_ids) and issue.name.available_copies <= 0:
+ raise Warning(_("Warning"), _("Sorry, Currently book not available"))
+ elif issue.card_id.book_limit <= len(card_ids) and issue.name.available_copies <= 0:
+ raise Warning(_("Warning"), _("Sorry, Currently book not available and Exceeded maximum book limit..."))
+ else:
+ pass
+ return True
+
+ def user_fine(self, cr, uid, ids, context=None):
+ conf = self.pool.get('ir.values')
+ account_conf = conf.get_default(cr, uid, 'library.config.settings', 'account_id')
+ if account_conf == False or account_conf == None:
+ raise Warning(_("Warning"), _("Set an account for library from Library settings"))
+ lib_account = account_conf
+ for i in self.browse(cr, uid, ids):
+ state = i.state
+ book = i.name.id
+ issue_code = i.issue_code
+
+ invoice_obj = self.pool.get('account.invoice')
+ obj_data = self.pool.get('ir.model.data')
+ pen = 0.0
+ fine_per_day = 0.0
+ lost_pen = 0.0
+ for record in self.browse(cr, uid, ids):
+ a = record.date_return
+ a = datetime.strptime(a, DEFAULT_SERVER_DATETIME_FORMAT)
+
+ usr = record.user.id
+ addr = record.user.contact_address
+ user_account = record.user.property_account_receivable.id
+ vals_invoice = {
+ 'partner_id': usr,
+ 'address_invoice_id': addr,
+ 'date_invoice': date.today().strftime('%Y-%m-%d'),
+ 'account_id': user_account,
+ }
+ invoice_lines = []
+ if state == 'lost':
+ lost_pen = record.lost_penalty
+ invoice_line2 = {
+ 'name': issue_code,
+ 'price_unit': lost_pen,
+ 'product_id': book,
+ 'account_id': lib_account
+ }
+ invoice_lines.append((0, 0, invoice_line2))
+ if state != 'lost':
+ b = record.actual_return_date
+ b = datetime.strptime(b, DEFAULT_SERVER_DATETIME_FORMAT)
+ dif = b.date() - a.date()
+ day = dif.days
+
+ conf = self.pool.get('ir.values')
+ store_conf = conf.get_default(cr, uid, 'library.config.settings', 'fine_per_day')
+ fine_amount = store_conf
+
+ if fine_amount < 0.0:
+ raise Warning(_("Warning"),
+ _("Fine per day must be positive.Set a fine amount from Library settings"))
+ fine_per_day += fine_amount * day
+
+ invoicee_obj = self.pool.get('account.invoice.line')
+ invoicee_search = invoicee_obj.search(cr, uid, [])
+ for i in invoicee_obj.browse(cr, uid, invoicee_search, context=context):
+ if i.name == issue_code:
+ raise Warning(_("Warning"), _("Cannot create two invoice line with same issue code."))
+ if a < b:
+ pen = record.penalty + fine_per_day
+ invoice_line1 = {
+ 'name': issue_code,
+ 'price_unit': pen,
+ 'product_id': book,
+ 'account_id': lib_account
+ }
+ else:
+ invoice_line1 = {
+ 'name': issue_code,
+ 'price_unit': 0.00,
+ 'product_id': book,
+ 'account_id': lib_account
+ }
+
+ invoice_lines.append((0, 0, invoice_line1))
+ vals_invoice.update({'invoice_line': invoice_lines})
+ new_invoice_id = invoice_obj.create(cr, uid, vals_invoice)
+ data_id = obj_data._get_id(cr, uid, 'account', 'invoice_form')
+ data = obj_data.browse(cr, uid, data_id, context=context)
+ view_id = data.res_id
+ return {
+ 'name': _("New Invoice"),
+ 'view_mode': 'form',
+ 'view_id': [view_id],
+ 'view_type': 'form',
+ 'res_model': 'account.invoice',
+ 'type': 'ir.actions.act_window',
+ 'nodestroy': True,
+ 'res_id': new_invoice_id,
+ 'target': 'current',
+ 'context': {}
+ }
+
+ def reissue_book(self, cr, uid, ids, context=None):
+ new = self.pool.get('library.book.issue').browse(cr, uid, ids, context=context)
+ day_to_return_book = new.day_to_return_book.id
+ return_days = self.pool.get('library.book.returnday')
+ browse = return_days.browse(cr, uid, day_to_return_book, context)
+ for item in browse:
+ day = item.day
+ ret_date = datetime.now() + timedelta(days=day)
+ self.write(cr, uid, ids, {'state': 'reissue'}, context=context)
+ self.write(cr, uid, ids, {'date_issue': datetime.now(), 'date_return': ret_date}, context=context)
+ return True
+
+ def lost_book(self, cr, uid, ids, context=None):
+ product_obj = self.pool.get('product.product')
+ for issue in self.browse(cr, uid, ids, context=context):
+ avail = issue.name.available_copies
+ total = issue.name.total_copies - 1
+ product_obj.write(cr, uid, issue.name.id, {'total_copies': total}, context=context)
+ product_obj.write(cr, uid, issue.name.id, {'available_copies': avail}, context=context)
+ self.write(cr, uid, ids, {'state': 'lost'}, context=context)
+ return True
+
+ def return_book(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids):
+ product_rec = self.pool.get('product.product').browse(cr, uid, order.name.id, context=context)
+ book = product_rec.name
+ searc = self.pool.get('product.product').search(cr, uid, [('product_tmpl_id', '=', book)])
+ conf = self.pool.get('ir.values')
+ store_conf = conf.get_default(cr, uid, 'library.config.settings', 'store')
+ ware_brow = self.pool.get('stock.warehouse').browse(cr, uid, store_conf, context=context)
+ if store_conf == False:
+ raise Warning(_("Warning"), _("Set a store to library from Library settings"))
+ whstocks = self.pool.get('stock.location'). \
+ search(cr, uid, [('location_id.name', '=', ware_brow.code), ('name', '=', 'Stock')], context=context)
+ whstock = whstocks[0]
+ whsto = self.pool.get('stock.location').browse(cr, uid, whstock, context=None)
+ search_picks = self.pool.get('stock.picking.type'). \
+ search(cr, uid, [('warehouse_id.name', '=', ware_brow.name)], context=context)
+ search_pick = search_picks[0]
+ picking_vals = {
+ 'picking_type_id': search_pick,
+ 'partner_id': order.user.id,
+ 'date': date.today(),
+ 'origin': order.issue_code,
+ }
+ picking_id = self.pool.get('stock.picking').create(cr, uid, picking_vals, context=context)
+ vals = {
+ 'name': order.id or '',
+ 'product_id': searc[0],
+ 'product_uom': product_rec.uom_id.id,
+ 'date': date.today(),
+ 'location_id': order.user.property_stock_customer.id,
+ 'location_dest_id': whsto.id,
+ 'picking_id': picking_id,
+
+ }
+ move_id = self.pool.get('stock.move').create(cr, uid, vals, context=context)
+ self.pool.get('stock.move').force_assign(cr, uid, [move_id], context=context)
+ return {
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'stock.picking',
+ 'context': context,
+ 'type': 'ir.actions.act_window',
+ 'res_id': picking_id
+ }
+
+ def cancel_book(self, cr, uid, ids, context=None):
+ product_obj = self.pool.get('product.product')
+ for issue in self.browse(cr, uid, ids, context=context):
+ avail = issue.name.available_copies + 1
+ product_obj.write(cr, uid, issue.name.id, {'availability': 'available', 'available_copies': avail}, context)
+ self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
+ return True
+
+ def draft_book(self, cr, uid, ids, context=None):
+ self.write(cr, uid, ids, {'state': 'draft'}, context=context)
+ return True
+
+ def onchange_card_id(self, cr, uid, ids, card_id, context=None):
+
+ if card_id:
+ card_detail = self.pool.get('library.card')
+ browse = card_detail.browse(cr, uid, card_id, context)
+ for item in browse:
+ user = item.username
+ return {'value': {'user': user}}
+
+ def on_change_book_name(self, cr, uid, ids, book_name, context=None):
+ if book_name:
+ fine = 0.0
+ for line in self.browse(cr, uid, book_name, context=context):
+ book = self.pool.get('product.product')
+ bb = book.browse(cr, uid, book_name, context)
+ fine = bb.lst_price
+ return {'value': {'lost_penalty': fine}}
+
+ def on_change_day_to_return(self, cr, uid, ids, day_to_return_book, context=None):
+ if day_to_return_book:
+ new = self.pool.get('library.book.issue').browse(cr, uid, ids, context=context)
+ datee = new.date_issue
+ date = datetime.strptime(str(datee), DEFAULT_SERVER_DATETIME_FORMAT)
+ return_days = self.pool.get('library.book.returnday')
+ browse = return_days.browse(cr, uid, day_to_return_book, context)
+ for item in browse:
+ day = item.day
+ penalty = item.fine_amt
+ ret_date = date + timedelta(days=day)
+ self.write(cr, uid, ids, {'date_return': ret_date, 'penalty': penalty}, context)
+ return {'value': {'date_return': ret_date, 'penalty': penalty}}
+
+
+class card_details(models.Model):
+ _name = 'library.card'
+ name = fields.Char(string='Card No', size=64, required=True)
+ username = fields.Many2one('res.partner', "User Name", required=True)
+ have_valid_card = fields.Boolean('Have valid Card')
+ book_limit = fields.Integer("Book Limit", required=True)
+ account_ids = fields.One2many('library.book.issue', compute='compute_account')
+ _sql_constraints = [('name_uniq', 'unique (name)', 'The card name must be unique !')]
+ _defaults = {'name': lambda self, cr, uid, context: 'card',
+ 'have_valid_card': False}
+
+ def copy(self, cr, uid, id, default=None, context=None):
+ raise Warning(_('Forbbiden to duplicate'),
+ _('It is not possible to duplicate the record, please create a new one.'))
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('name', _('card')) == _('card'):
+ values['name'] = self.pool.get('ir.sequence').get(cr, uid, 'library.card')
+ return super(card_details, self).create(cr, uid, values, context=context)
+
+ def compute_account(self):
+ issue_obj = self.pool.get('library.book.issue')
+ browse = self.browse(self._ids)
+ student_ids = issue_obj.search(self._cr, self._uid, [('card_id', '=', browse.name)])
+ self.account_ids = student_ids
+
+ def onchange_username(self, cr, uid, ids, username, context=None):
+ if username:
+ card_obj = self.pool.get('library.card')
+ card_ids = card_obj.search(cr, uid, [('username', '=', username), ('have_valid_card', '=', True)])
+ if len(card_ids) > 0:
+ return {'value': {'username': " ", 'user': False, 'book_limit': 0},
+ 'warning': {'title': 'Warning', 'message': 'Already the user have a card !'}}
+
+ reg_obj = self.pool.get('library.registration')
+ reg_user_draft = reg_obj.search(cr, uid, [('name', '=', username), ('state', '=', 'draft')])
+ length_draft = len(reg_user_draft)
+ if length_draft > 0:
+ return {'value': {'username': " ", 'user': False, 'book_limit': 0},
+ 'warning': {'title': 'Warning',
+ 'message': 'Already the user have a registration in draft state!'}}
+
+ reg_user_cancel = reg_obj.search(cr, uid, [('name', '=', username), ('state', '=', 'cancel')])
+ length_cancel = len(reg_user_cancel)
+ if length_cancel > 0:
+ return {'value': {'username': " ", 'user': False, 'book_limit': 0},
+ 'warning': {'title': 'Warning',
+ 'message': 'Already the user have a registration in cancel state!'}}
+ reg_user_reg = reg_obj.search(cr, uid, [('name', '=', username), ('state', '=', 'registered')])
+ length_reg = len(reg_user_reg)
+ if length_reg == 0:
+ return {'value': {'username': " ", 'user': False, 'book_limit': 0},
+ 'warning': {'title': 'Warning',
+ 'message': 'Card not allowed for users without valid registration!'}}
+
+
+ # def onchange_user(self, cr, uid, ids, user, context=None):
+ # if user:
+ # if user == 'student':
+ # booklimit = 3
+ # if user == 'teacher':
+ # booklimit = 5
+ # if user == 'others':
+ # booklimit = 2
+ # self.write(cr, uid, ids,{'book_limit': booklimit}, context)
+ # return {'value': {'book_limit': booklimit}}
+
+
+class library_validity(models.Model):
+ _name = 'library.validity'
+ _rec_name = 'code'
+ code = fields.Char('Code', readonly=True, size=16)
+ name = fields.Char('Name', readonly=True, default="0 Years, 0 Months, 0 Days", compute='compute_validity')
+ year = fields.Integer('Year')
+ month = fields.Integer('Month')
+ day = fields.Integer('Day')
+ _defaults = {'code': lambda self, cr, uid, context: 'Validity'}
+
+ def create(self, cr, uid, values, context=None):
+ val_obj = self.search(cr, uid, [])
+ for rcd in val_obj:
+ val_details = self.browse(cr, uid, rcd, context)
+ if val_details.year == values['year'] and val_details.month == values['month'] and val_details.day == \
+ values['day']:
+ raise Warning(_("Warning"), _("The record with same validity period already exists."))
+
+ if values.get('code', _('Validity')) == _('Validity'):
+ values['code'] = self.pool.get('ir.sequence').get(cr, uid, 'library.validity')
+ return super(library_validity, self).create(cr, uid, values, context=context)
+
+ def write(self, cr, uid, ids, vals, context=None):
+ year = month = day = 0
+ if 'year' in vals:
+ year = vals['year']
+ if 'month' in vals:
+ month = vals['month']
+ if 'day' in vals:
+ day = vals['day']
+ if context is None:
+ context = {}
+ val_obj = self.search(cr, uid, [])
+ for rcd in val_obj:
+ val_details = self.browse(cr, uid, rcd, context)
+ if val_details.year == year and val_details.month == month and val_details.day == day:
+ raise Warning(_("Warning"), _("The record with same validity period already exists."))
+
+ return super(library_validity, self).write(cr, uid, ids, vals, context=context)
+
+ @api.depends('year', 'month', 'day')
+ def compute_validity(self):
+ year = self.year
+ month = self.month
+ day = self.day
+ validity = str(year) + " Years," + str(month) + " Months," + str(day) + " Days"
+ self.name = validity
+
+
+class res_partner(models.Model):
+ _inherit = 'res.partner'
+ librarian = fields.Boolean('librarain')
+ _defaults = {'librarian': False,
+ }
+
+
+class library_books(models.Model):
+ _inherit = 'product.product'
+ book = fields.Boolean('Book')
+ editor = fields.Many2one('res.partner', 'Editor', change_default=True)
+ author = fields.Many2one('library.author', 'Author', size=30)
+ publisher = fields.Many2one('library.publisher', 'Publisher', size=30)
+ total_copies = fields.Integer('Total Copies')
+ available_copies = fields.Integer('Available Copies')
+ book_cat = fields.Many2one('library.price.category', "Book Category")
+ availability = fields.Boolean('Available', default=True)
+ year_of_publication = fields.Integer('Year of Publication')
+ barcode = fields.Char('Barcode')
+ rack = fields.Many2one('library.rack', 'Rack', size=16, help="it will be show the position of book")
+ isbn = fields.Char('ISBN Code', size=64, unique=True, help="It show the International Standard Book Number")
+ lang = fields.Many2one('product.lang', 'Language')
+ date_parution = fields.Date('Release date', help="Release(Issue) date of the book")
+ creation_date = fields.Datetime('Creation date', readonly=True, help="Record creation date")
+ date_retour = fields.Date('Return Date', readonly=True, help='Book Return date')
+ nbpage = fields.Integer('Number of pages', size=8)
+ back = fields.Selection([('hard', 'Hardback'), ('paper', 'Paperback')], 'Reliure',
+ help="It show the books binding type")
+ pocket = fields.Char('Pocket', size=32)
+ num_pocket = fields.Char('Collection Num.', size=32, help="It show the collection number in which book is resides")
+ num_edition = fields.Integer('Num. edition', help="Edition number of book")
+ format = fields.Char('Format', help="The general physical appearance of a book")
+ history_ids = fields.One2many('library.book.issue', compute='compute_history')
+ _sql_constraints = [
+
+ ('unique_ean13', 'unique(ean13)', 'The ean13 field must be unique across all the products'),
+ ('code_uniq', 'unique (code)', 'The code of the product must be unique !')]
+ _defaults = {'availability': 'available',
+ }
+
+ def compute_history(self):
+ book_obj = self.pool.get('library.book.issue')
+ browse = self.browse(self._ids)
+ student_ids = book_obj.search(self._cr, self._uid, [('name', '=', browse.name)])
+ self.history_ids = student_ids
+
+ def _get_default_image(self, cr, uid, is_company, context=None, colorize=False):
+ image_medium = image_colorize(
+ open(openerp.modules.get_module_resource('library_management', 'static/src/img', 'book1.png')).read())
+ return image_resize_image_big(image_medium.encode('base64'))
+
+ def onchange_total(self, cr, uid, ids, total_copies, context=None):
+ prod_obj = self.pool.get('product.product')
+ for issue in self.browse(cr, uid, ids, context=context):
+ prod_obj.write(cr, uid, issue.id, {'available_copies': total_copies}, context)
+ return {'value': {'available_copies': total_copies}}
+
+ # def create(self, cr, uid, values, context=None):
+ # values['book'] = True
+ # return super(library_books, self).create(cr, uid, values, context=context)
+
+
+class library_author(models.Model):
+ _name = 'library.author'
+ name = fields.Char('Name', size=30, required=True, select=True)
+ code = fields.Char('Code', readonly=True)
+ born_date = fields.Date('Date of Birth')
+ death_date = fields.Date('Date of Death')
+ biography = fields.Text('Biography')
+ note = fields.Text('Notes')
+ book_ids = fields.One2many('product.product', compute='compute_book')
+ _sql_constraints = [('name_uniq', 'unique (name)', 'The name of the author must be unique !'),
+ ('code_uniq', 'unique (code)', 'The code of the collection must be unique !')]
+ _defaults = {'code': lambda self, cr, uid, context: 'author'}
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('code', _('author')) == _('author'):
+ values['code'] = self.pool.get('ir.sequence').get(cr, uid, 'library.author')
+ return super(library_author, self).create(cr, uid, values, context=context)
+
+ def unlink(self, cr, uid, ids, context=None):
+ author_obj = self.browse(cr, uid, ids)
+ book_obj = self.pool.get('product.product')
+ search_obj = book_obj.search(cr, uid, [('book', '=', True)])
+ for author in author_obj:
+ for i in search_obj:
+ if book_obj.browse(cr, uid, i).author.name == author.name:
+ raise Warning(_("Warning"), _("Deletion unsuccessful."),
+ _("Author refered in some records in books."))
+ # Call the parent method to eliminate the records.
+ super(library_author, self).unlink(cr, uid, ids, context)
+
+ def compute_book(self):
+ book_obj = self.pool.get('product.product')
+ browse = self.browse(self._ids)
+ student_ids = book_obj.search(self._cr, self._uid, [('author', '=', browse.name)])
+ self.book_ids = student_ids
+
+
+class library_publisher(models.Model):
+ _name = 'library.publisher'
+ name = fields.Char('Name', size=30, required=True)
+ code = fields.Char('Code', readonly=True)
+ _sql_constraints = [('code_uniq', 'unique (code)', 'The code of the publisher must be unique !')]
+ _defaults = {'code': lambda self, cr, uid, context: 'publisher'}
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('code', _('publisher')) == _('publisher'):
+ values['code'] = self.pool.get('ir.sequence').get(cr, uid, 'library.publisher')
+ return super(library_publisher, self).create(cr, uid, values, context=context)
+
+
+class tranfer_wizard(models.Model):
+ _inherit = 'stock.transfer_details'
+
+ @api.one
+ def do_detailed_transfer(self, context=None):
+ active_id = context.get('active_ids')
+ processed_ids = []
+ # Create new and update existing pack operations
+ for lstits in [self.item_ids, self.packop_ids]:
+ for prod in lstits:
+ pack_datas = {
+ 'product_id': prod.product_id.id,
+ 'product_uom_id': prod.product_uom_id.id,
+ 'product_qty': prod.quantity,
+ 'package_id': prod.package_id.id,
+ 'lot_id': prod.lot_id.id,
+ 'location_id': prod.sourceloc_id.id,
+ 'location_dest_id': prod.destinationloc_id.id,
+ 'result_package_id': prod.result_package_id.id,
+ 'date': prod.date if prod.date else datetime.now(),
+ 'owner_id': prod.owner_id.id,
+ }
+ if prod.packop_id:
+ prod.packop_id.with_context(no_recompute=True).write(pack_datas)
+ processed_ids.append(prod.packop_id.id)
+ else:
+ pack_datas['picking_id'] = self.picking_id.id
+ packop_id = self.env['stock.pack.operation'].create(pack_datas)
+ processed_ids.append(packop_id.id)
+ # Delete the others
+ packops = self.env['stock.pack.operation'].search(
+ ['&', ('picking_id', '=', self.picking_id.id), '!', ('id', 'in', processed_ids)])
+ packops.unlink()
+ # Execute the transfer of the picking
+ self.picking_id.do_transfer()
+ issue_code_search = self.pool.get('stock.picking').browse(self._cr, self._uid, active_id)
+ for i in issue_code_search:
+ issue_code = i.origin
+ picking_type = i.picking_type_id.name
+ issue_obj = self.pool.get('library.book.issue')
+ issue_search = issue_obj.search(self._cr, self._uid, [('issue_code', '=', issue_code)])
+ issue_browse = issue_obj.browse(self._cr, self._uid, issue_search)
+ product_obj = self.pool.get('product.product')
+ if picking_type == 'Receipts':
+ for i in issue_browse:
+ issue_obj.write(self._cr, self._uid, issue_search,
+ {'state': 'return', 'actual_return_date': datetime.now()})
+ avail = i.name.available_copies + 1
+ product_obj.write(self._cr, self._uid, i.name.id,
+ {'availability': 'available', 'available_copies': avail}, context)
+ else:
+ for i in issue_browse:
+ issue_obj.write(self._cr, self._uid, issue_search, {'state': 'transfered'})
+ avail = i.name.available_copies - 1
+ product_obj.write(self._cr, self._uid, i.name.id, {'available_copies': avail}, context)
+ return True
+
+
+class account_wizard(models.Model):
+ _inherit = 'account.voucher'
+
+ def button_proforma_voucher(self, cr, uid, ids, context=None):
+ active_id = context.get('active_ids')
+ self.pool.get('account.invoice').write(cr, uid, active_id, {'state': 'paid'})
+ account_obj = self.pool.get('account.invoice').browse(cr, uid, active_id)
+ for i in account_obj.invoice_line:
+ issue = i.name
+ issue_obj = self.pool.get('library.book.issue')
+ issue_search = issue_obj.search(cr, uid, [('issue_code', '=', issue)])
+ for i in issue_search:
+ issue_obj.write(cr, uid, i, {'state': 'paid'})
+ return {'type': 'ir.actions.act_window_close'}
diff --git a/library_management/registration.py b/library_management/registration.py
new file mode 100644
index 000000000..c44f354a3
--- /dev/null
+++ b/library_management/registration.py
@@ -0,0 +1,244 @@
+from openerp import models, fields, api
+import openerp
+from datetime import datetime,time,date,timedelta
+from openerp.tools.translate import _
+from openerp.exceptions import Warning
+from openerp.tools import image_colorize, image_resize_image_big
+
+
+class library_registratin(models.Model):
+ _name = "library.registration"
+ _rec_name = 'name'
+ validity = fields.Many2one('library.validity', 'Validity')
+ from_id = fields.Date(string='Valid From')
+ to = fields.Date(string='Valid To', compute='compute_valid_to')
+ notes = fields.Text('Notes')
+ photo = fields.Binary('Photo')
+ name = fields.Many2one('res.partner', string='Member', size=64, required=True)
+ card_no = fields.Char(string='Card No', size=64, readonly=True, help='Unique Card No', copy=False)
+ registration_date = fields.Date('Registration Date')
+ phone = fields.Char('Phone', size=12)
+ mobile = fields.Char('Mobile', size=12)
+ state = fields.Selection([('draft', 'Draft'), ('registered', 'Registered'),('assigned_card', 'Card Assigned'), ('cancel', 'Cancel')])
+ user = fields.Char("Position")
+ book_limit = fields.Integer("Book Limit", required=True)
+ _sql_constraints = [('card_no.unique', 'unique(card_no)', 'already existing request id. try another ID')]
+ _defaults = {
+ 'card_no': lambda obj, cr, uid, context: 'Registration no',
+ 'state': 'draft',
+ 'photo': lambda self, cr, uid, ctx: self._get_default_image(cr, uid, ctx.get('default_is_company', False), ctx),
+ }
+
+ @api.depends('from_id', 'validity')
+ def compute_valid_to(self):
+ if self.validity:
+ days = 0
+ if self.validity.year:
+ days += self.validity.year*365
+ if self.validity.month:
+ days += self.validity.month*30
+ if self.validity.day:
+ days += self.validity.day
+ from_id = datetime.strptime(str(self.from_id), '%Y-%m-%d')
+ to = from_id + timedelta(days=days)
+ self.to = to
+
+ def unlink(self, cr, uid, ids, context=None):
+ reg_obj = self.browse(cr, uid, ids)
+ issue_obj = self.pool.get('library.book.issue')
+ search_obj = issue_obj.search(cr, uid, [])
+ for reg in reg_obj:
+ for i in search_obj:
+ if issue_obj.browse(cr, uid, i).user == reg.name:
+ raise Warning(_("Warning"), _("Deletion unsuccessful."),
+ _("User have some book issues. Delete those records first!!"))
+ super(library_registratin, self).unlink(cr, uid, ids, context)
+
+ def create(self, cr, uid, values, context=None):
+ if values.get('card_no', _('Registration no')) == _('Registration no'):
+ values['card_no'] = self.pool.get('ir.sequence').get(cr, uid, 'reg.no')
+ return super(library_registratin, self).create(cr, uid, values, context=context)
+
+ def _registered_user_manager(self, cr, uid, context=None):
+ today = date.today()
+ reg_obj = self.pool.get('library.registration')
+ late_ids = reg_obj.search(cr, uid, [('to', '<', today)])
+ for i in late_ids:
+ reg_obj.write(cr, uid, i, {'state': 'cancel'})
+
+ def _get_default_image(self, cr, uid, is_company, context=None, colorize=False):
+ image = image_colorize(open(openerp.modules.get_module_resource('base', 'static/src/img', 'avatar.png')).read())
+ return image_resize_image_big(image.encode('base64'))
+
+ def getdata(self, cr, uid, ids, name, context=None):
+ reg_obj = self.pool.get('library.registration')
+ reg_user_registered = reg_obj.search(cr, uid, [('name', '=', name), ('state', '=', 'registered')])
+ length_registered = len(reg_user_registered)
+ reg_user_assigned_card = reg_obj.search(cr, uid, [('name', '=', name), ('state', '=', 'assigned_card')])
+ length_assigned_card = len(reg_user_assigned_card)
+ reg_user_cancel = reg_obj.search(cr, uid, [('name', '=', name), ('state', '=', 'cancel')])
+ length_cancel = len(reg_user_cancel)
+ reg_user_draft = reg_obj.search(cr, uid, [('name', '=', name), ('state', '=', 'draft')])
+ length_draft = len(reg_user_draft)
+ if length_draft == 1:
+ return {'value': {'name': " "}, 'warning': {'title': 'Warning',
+ 'message': 'User already have a record for registration in draft state'}}
+ if length_cancel == 1:
+ return {'value': {'name': " "}, 'warning': {'title': 'Warning',
+ 'message': 'User already have a record for registration in cancel state'}}
+ if length_assigned_card == 1 or length_registered == 1:
+ return {'value': {'name': " "}, 'warning': {'title': 'Warning',
+ 'message': 'User already have a record for registration'}}
+ obj = self.pool.get('res.partner')
+ rec = obj.browse(cr, uid, name, context=None)
+ for i in rec:
+ return {'value': {'mobile': i.mobile, 'phone': i.phone}}
+
+ def register(self, cr, uid, ids, context=None):
+ # flag = 0
+ pool_reg = self.pool.get('library.registration')
+ pool_partner = self.pool.get('res.partner')
+ lib_rec = pool_reg.browse(cr, uid, ids, context=None)
+ child_name = lib_rec.name.id
+ res_part_browse1 = pool_partner.browse(cr, uid, [child_name], context=None)
+ if res_part_browse1.librarian == True:
+ raise Warning(_("Warning"), _("Already registered..."))
+ else:
+ reg_date = date.today()
+ a = timedelta(days=365)
+ b = reg_date + a
+ self.write(cr, uid, ids, {'registration_date': reg_date, 'state': 'registered',
+ 'from_id': reg_date, 'to': b}, context=context)
+ res_part_browse1.write({'librarian': True })
+
+ def create_card(self, cr, uid, ids, context=None):
+ card_obj = self.pool.get('library.card')
+ for i in self.browse(cr, uid, ids):
+ username = i.name
+ card_ids = card_obj.search(cr, uid, [('id', '=', i.id), ('have_valid_card', '=', True)])
+ if len(card_ids) > 0:
+ raise Warning(_("Warning"), _("Already the user have a card !"))
+ vals = {
+ 'username': username.id,
+ 'book_limit': i.book_limit
+ }
+ new_card_id = card_obj.create(cr, uid, vals)
+ self.write(cr, uid, ids, {'state': 'assigned_card'}, context=context)
+ obj_data = self.pool.get('ir.model.data')
+ data_id = obj_data._get_id(cr, uid, 'library_management', 'product_card_form_view')
+ data = obj_data.browse(cr, uid, data_id, context=context)
+ view_id = data.res_id
+ card_rec = card_obj.browse(cr, uid, new_card_id, context=context)
+ card_obj.write(cr, uid, card_rec.id, {'have_valid_card': True}, context=context)
+ return {
+ 'name': _("New card"),
+ 'view_mode': 'form',
+ 'view_id': [view_id],
+ 'view_type': 'form',
+ 'res_model': 'library.card',
+ 'type': 'ir.actions.act_window',
+ 'nodestroy': True,
+ 'res_id': new_card_id,
+ 'target': 'current',
+ 'context': {}
+ }
+
+ def cancel(self, cr, uid, ids, context=None):
+ user_issue = self.browse(cr,uid,ids).name.id
+ pool_partner = self.pool.get('res.partner')
+ res_part_browse1 = pool_partner.browse(cr, uid, user_issue, context=None)
+ res_part_browse1.write({'librarian': False })
+ card_obj = self.pool.get('library.card')
+ card_search = card_obj.search(cr, uid, [('username', '=', user_issue)])
+ for i in card_search:
+ card_rec = card_obj.browse(cr, uid, i)
+ card_obj.write(cr, uid, card_rec.id, {'have_valid_card': False}, context=context)
+ # self.unlink(cr, uid, ids, context=context)
+ self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
+ return True
+ # pool_issue = self.pool.get('library.book.issue')
+ # pool_card = self.pool.get('library.card')
+ # issues = pool_issue.search(cr, uid, [('user', '=', user_issue)])
+ # for items in issues:
+ # book = pool_issue.browse(cr, uid, items).issue_code
+ # if pool_issue.browse(cr, uid, items).state =='transfered':
+ # raise Warning(_("Warning"), _("Please return book before cancelling registration"),
+ # _("Issue no:"), book)
+ # if pool_issue.browse(cr, uid, items).state =='return':
+ # raise Warning(_("Warning"), _("Please pay fine of the returned book before cancelling registration"),
+ # _("Issue no:"), book)
+ # if pool_issue.browse(cr, uid, items).state =='lost':
+ # raise Warning(_("Warning"), _("Please pay fine of the losted book before cancelling registration"),
+ # _("Issue no:"), book)
+ # if pool_issue.browse(cr, uid, items).state =='reissue':
+ # raise Warning(_("Warning"), _("Please return the book before cancelling registration"),
+ # _("Issue no:"), book)
+ # cr.execute('DELETE FROM library_book_issue WHERE id = %s', ([items]))
+ # card = pool_card.search(cr, uid, [('username', '=', user_issue)])
+ # for i in card:
+ # cr.execute('DELETE FROM library_card WHERE id = %s', ([i]))
+
+ def draft(self, cr, uid, ids, context=None):
+ self.write(cr, uid, ids, {'state': 'draft'}, context=context)
+ return True
+
+ def renew(self, cr, uid, ids, context=None):
+ reg_date = date.today()
+ a = timedelta(days=365)
+ b = reg_date + a
+ self.write(cr, uid, ids, {'registration_date': reg_date, 'state': 'assigned_card',
+ 'from_id': reg_date, 'to': b}, context=context)
+
+
+class user_user(models.Model):
+ _name = "res.partner"
+ _inherit = 'res.partner'
+ position = fields.Selection([('student', 'Student'), ('teacher', 'Teacher'), ('other', 'Other')],
+ 'Position', required=True)
+ reader = fields.Boolean('Reader', help="Check this box if this contact is a reader.", default=True)
+ _defaults = {
+ 'image': lambda self, cr, uid, ctx: self._get_default_image(cr, uid, ctx.get('default_is_company', False), ctx)
+ }
+
+ def _get_default_image(self, cr, uid, is_company, context=None, colorize=False):
+ image = image_colorize(open(openerp.modules.get_module_resource('base', 'static/src/img', 'avatar.png')).read())
+ return image_resize_image_big(image.encode('base64'))
+
+
+class Wizard(models.TransientModel):
+ _name = 'book.report'
+ book = fields.Many2one('product.product', "Book")
+ rack = fields.Many2one("library.rack", 'Rack')
+ author = fields.Many2one("library.author", 'Author')
+ language = fields.Many2one('product.lang', 'Language')
+ catag = fields.Many2one('library.price.category', "Book category")
+
+ def confirmfilter(self, cr, uid, ids, context=None):
+ i = self.browse(cr, uid, ids, context=None)
+ book_name = i.book.name
+ rack = i.rack.name
+ author_name = i.author.name
+ lang = i.language.name
+ catag = i.catag.name
+ dom = [('book', '=', True)]
+ if book_name != False:
+ dom = [('name', '=', book_name)]
+ if rack != False:
+ dom.append(('rack', '=', rack))
+ if author_name != False:
+ dom.append(('author', '=', author_name))
+ if lang != False:
+ dom.append(('lang', '=', lang))
+ if catag != False:
+ dom.append(('book_cat', '=', catag))
+
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': 'FILTERED BOOKS',
+ 'view_type': 'tree',
+ 'view_mode': 'tree',
+ 'res_model': 'product.product',
+ 'target': 'current',
+ 'domain': dom
+ }
+
diff --git a/library_management/report.xml b/library_management/report.xml
new file mode 100644
index 000000000..72c23c0e9
--- /dev/null
+++ b/library_management/report.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library_management/report/__init__.py b/library_management/report/__init__.py
new file mode 100644
index 000000000..8c7f0de15
--- /dev/null
+++ b/library_management/report/__init__.py
@@ -0,0 +1 @@
+import report_invoice_parser
\ No newline at end of file
diff --git a/library_management/report/report_invoice_parser.py b/library_management/report/report_invoice_parser.py
new file mode 100644
index 000000000..a7bc15709
--- /dev/null
+++ b/library_management/report/report_invoice_parser.py
@@ -0,0 +1,34 @@
+from openerp import models
+from openerp.report import report_sxw
+from datetime import date
+class report_lib(report_sxw.rml_parse):
+ _name = 'report.library_management.report_invoice_library'
+ def __init__(self, cr, uid, name, context=None):
+ if context is None:
+ context = {}
+ super(report_lib, self).__init__(cr, uid, name, context = context)
+ self.localcontext.update({
+ 'timee':self._timee,
+ 'get_data': self._get_data,
+
+ })
+ def _timee(self,data):
+ date_now=date.today().strftime('%Y-%m-%d')
+ return date_now
+
+ def _get_data(self,issue_code):
+ acc_obj=self.pool.get('account.invoice.line')
+ search = acc_obj.search(self.cr,self.uid,[('name', '=', issue_code)])
+ var = acc_obj.browse(self.cr, self.uid, search)
+ descri = var.name
+ product = var.product_id
+ quant = var.quantity
+ price = var.price_unit
+ subtotal = var.price_subtotal
+ return {'descri': descri, 'product': product.name,'quant': quant,'price': price,'subtotal': subtotal}
+
+class report_lib_invoice(models.AbstractModel):
+ _name = 'report.library_management.report_invoice_library'
+ _inherit = 'report.abstract_report'
+ _template = 'library_management.report_invoice_library'
+ _wrapped_report_class = report_lib
\ No newline at end of file
diff --git a/library_management/res_config.py b/library_management/res_config.py
new file mode 100644
index 000000000..1c9c83f38
--- /dev/null
+++ b/library_management/res_config.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+from openerp import SUPERUSER_ID
+from openerp.tools.translate import _
+from openerp.osv import fields, osv
+
+
+class PropertyConfigSettings(osv.TransientModel):
+ _name = 'library.config.settings'
+ _inherit = 'res.config.settings'
+
+ def _default_company(self, cr, uid, context=None):
+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ return user.company_id.id
+
+ _columns = {
+ 'store': fields.many2one('stock.warehouse', _('Library Store'), help=_('Account used for Library Configuration')),
+ 'account_id': fields.many2one('account.account', _('Library Account'),
+ domain="[('type', '=', 'receivable')]",
+ help=_('Account used for Library Configuration')),
+ 'fine_per_day': fields.float(_('Fine per day')),
+
+ }
+
+ def get_default_store(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ store = ir_values.get_default(cr, uid, 'library.config.settings', 'store')
+ return {
+ 'store': store,
+ }
+
+ def set_store(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ wizard = self.browse(cr, uid, ids)[0]
+ if wizard.store:
+ store = wizard.store
+ ir_values.set_default(cr, SUPERUSER_ID, 'library.config.settings', 'store', store.id)
+ else:
+ store = False
+ ir_values.set_default(cr, SUPERUSER_ID, 'library.config.settings', 'store', store)
+
+ def get_default_account_id(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ account_id = ir_values.get_default(cr, uid, 'library.config.settings', 'account_id')
+ return {
+ 'store': account_id,
+ }
+
+ def set_account_id(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ wizard = self.browse(cr, uid, ids)[0]
+ if wizard.account_id:
+ account_id = wizard.account_id
+ ir_values.set_default(cr, SUPERUSER_ID, 'library.config.settings', 'account_id', account_id.id)
+ else:
+ account_id = False
+ ir_values.set_default(cr, SUPERUSER_ID, 'library.config.settings', 'account_id', account_id)
+
+ def get_default_fine_per_day(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ fine_per_day = ir_values.get_default(cr, uid, 'library.config.settings', 'fine_per_day')
+ return {
+ 'store': fine_per_day,
+ }
+
+ def set_fine_per_day(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ wizard = self.browse(cr, uid, ids)[0]
+ if wizard.fine_per_day:
+ fine_per_day = wizard.fine_per_day
+ ir_values.set_default(cr, SUPERUSER_ID, 'library.config.settings', 'fine_per_day', fine_per_day)
+ else:
+ fine_per_day = 0.0
+ ir_values.set_default(cr, SUPERUSER_ID, 'library.config.settings', 'store',fine_per_day)
\ No newline at end of file
diff --git a/library_management/res_config_view.xml b/library_management/res_config_view.xml
new file mode 100644
index 000000000..dbfbb6e26
--- /dev/null
+++ b/library_management/res_config_view.xml
@@ -0,0 +1,53 @@
+
+
+
+
+ Library settings
+ library.config.settings
+
+
+
+
+
+
+ Configure library
+ ir.actions.act_window
+ library.config.settings
+ form
+ inline
+
+
+
+
+
diff --git a/library_management/security/ir.model.access.csv b/library_management/security/ir.model.access.csv
new file mode 100644
index 000000000..c1d2b0965
--- /dev/null
+++ b/library_management/security/ir.model.access.csv
@@ -0,0 +1,29 @@
+id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
+access_library_registration,access_library_registration,model_library_registration,Administrator_group,1,1,1,1
+access_library_card,access_library_card,model_library_card,Administrator_group,1,1,1,1
+access_library_author,access_library_author,model_library_author,Administrator_group,1,1,1,1
+access_library_publisher,access_library_publisher,model_library_publisher,Administrator_group,1,1,1,1
+access_product_product,access_product_product,model_product_product,Administrator_group,1,1,1,1
+access_res_partnerr,access_res_partnerr,model_res_partner,Administrator_group,1,1,1,1
+access_stock_change_product_qty,access_stock_change_product_qty,model_stock_change_product_qty,Administrator_group,1,1,1,1
+access_library_rack,access_library_rack,model_library_rack,Administrator_group,1,1,1,1
+access_product_lang,access_product_lang,model_product_lang,Administrator_group,1,1,1,1
+access_library_book_returnday,access_library_book_returnday,model_library_book_returnday,Administrator_group,1,1,1,1
+access_library_price_category,access_library_price_category,model_library_price_category,Administrator_group,1,1,1,1
+access_library_book_issue,access_library_book_issue,model_library_book_issue,Administrator_group,1,1,1,1
+access_library_registration1,access_library_registration1,model_library_registration,librarian_group,1,1,1,1
+access_book_report1,access_book_report1,model_book_report,librarian_group,1,1,1,1
+access_library_card1,access_library_card1,model_library_card,librarian_group,1,1,1,1
+access_library_rack1,access_library_rack1,model_library_rack,librarian_group,1,1,1,1
+access_product_lang1,access_product_lang1,model_product_lang,librarian_group,1,1,1,1
+access_library_book_returnday1,access_library_book_returnday1,model_library_book_returnday,librarian_group,1,1,1,1
+access_library_price_category1,access_library_price_category1,model_library_price_category,librarian_group,1,1,1,1
+access_library_book_issue1,access_library_book_issue1,model_library_book_issue,librarian_group,1,1,1,1
+access_library_author1,access_library_author1,model_library_author,librarian_group,1,1,1,1
+access_library_publisher1,access_library_publisher1,model_library_publisher,librarian_group,1,1,1,1
+access_product_product1,access_product_product1,model_product_product,librarian_group,1,1,1,1
+access_res_partnerr1,access_res_partnerr1,model_res_partner,librarian_group,1,1,1,1
+access_stock_change_product_qty1,access_stock_change_product_qty1,model_stock_change_product_qty,librarian_group,1,1,1,1
+access_stock_transfer_details,access_stock_transfer_details,model_stock_transfer_details,,1,1,1,1
+access_library_validity,access_library_validity,model_library_validity,Administrator_group,1,1,0,0
+
diff --git a/library_management/security/library.account.config.csv b/library_management/security/library.account.config.csv
new file mode 100644
index 000000000..056f4f5c7
--- /dev/null
+++ b/library_management/security/library.account.config.csv
@@ -0,0 +1,2 @@
+"id"
+library_account_config_1
\ No newline at end of file
diff --git a/library_management/security/library.fine.per.day.conf.csv b/library_management/security/library.fine.per.day.conf.csv
new file mode 100644
index 000000000..6c89fd112
--- /dev/null
+++ b/library_management/security/library.fine.per.day.conf.csv
@@ -0,0 +1,2 @@
+"id"
+library_fine_per_day_conf_1
\ No newline at end of file
diff --git a/library_management/security/library.store.conf.csv b/library_management/security/library.store.conf.csv
new file mode 100644
index 000000000..5c74bb61b
--- /dev/null
+++ b/library_management/security/library.store.conf.csv
@@ -0,0 +1,2 @@
+"id"
+library_store_conf_1
\ No newline at end of file
diff --git a/library_management/static/description/icon.png b/library_management/static/description/icon.png
new file mode 100644
index 000000000..74f71b59e
Binary files /dev/null and b/library_management/static/description/icon.png differ
diff --git a/library_management/static/src/img/book1.png b/library_management/static/src/img/book1.png
new file mode 100644
index 000000000..bb77a5248
Binary files /dev/null and b/library_management/static/src/img/book1.png differ
diff --git a/library_management/view/library.xml b/library_management/view/library.xml
new file mode 100644
index 000000000..929297102
--- /dev/null
+++ b/library_management/view/library.xml
@@ -0,0 +1,722 @@
+
+
+
+
+
+
+
+
+
+ Rack
+ library.rack
+
+
+
+ Rack
+ library.rack
+ RACK
+ 3
+
+
+
+ library.rack.form
+ library.rack
+
+
+
+
+
+
+
+ library.rack.tree
+ library.rack
+
+
+
+
+
+
+
+
+
+
+
+ library.rack.search
+ library.rack
+
+
+
+
+
+
+
+
+
+
+
+ Library Rack
+ ir.actions.act_window
+ library.rack
+ form
+ tree,form
+
+
+ Language
+ product.lang
+
+
+
+ Language
+ product.lang
+ L
+ 3
+
+
+
+ Languages
+ product.lang
+ ir.actions.act_window
+ form
+ tree,form
+
+
+ product.lang.tree
+ product.lang
+
+
+
+
+
+
+
+
+
+
+
+
+ product.lang.form
+ product.lang
+
+
+
+
+
+ returnday
+ library.book.returnday
+
+
+
+ returnday
+ library.book.returnday
+ D
+ 3
+
+
+ Book Return Days
+ library.book.returnday
+ ir.actions.act_window
+ form
+ tree,form
+
+
+ library.book.returnday.search
+ library.book.returnday
+
+
+
+
+
+
+
+
+
+ library.book.returnday.tree
+ library.book.returnday
+
+
+
+
+
+
+
+
+
+
+
+ library.book.returnday.form
+ library.book.returnday
+
+
+
+
+
+ authors
+ library.author
+
+
+
+ Book category
+ library.author
+ A
+ 3
+
+
+ Authors
+ library.author
+ ir.actions.act_window
+ form
+ tree,form
+
+
+
+ library.author.form
+ library.author
+
+
+
+
+
+ Book category
+ library.price.cat
+
+
+
+ Book category
+ library.price.cat
+ CAT
+ 3
+
+
+ Price Category
+ ir.actions.act_window
+ library.price.category
+ form
+ tree,form
+
+
+ library.price.category
+ library.price.category
+
+
+
+
+
+
+
+
+
+
+ library.price.category
+ library.price.category
+
+
+
+
+
+
+ publisher
+ library.publisher
+
+
+
+ publisher
+ library.publisher
+ P
+ 3
+
+
+ Books
+ library.books
+
+
+
+ Books
+ library.books
+ B
+ 3
+
+
+ Books
+ product.product
+ ir.actions.act_window
+ form
+ tree,form
+ [('book','=',True)]
+ {'search_default_book':1, 'default_book': True}
+
+
+
+
+
+ library.book.issue.search.1
+ library.book.issue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Book Issues
+ library.book.issue
+ tree,form
+ form
+
+
+
+ library.book.issue.tree
+ library.book.issue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ library.book.issue.form
+ library.book.issue
+
+
+
+
+
+
+
+ Library Card No
+ library.card
+
+
+
+ Library Card No
+ library.card
+ C
+ 1
+ 3
+
+
+
+ Book issues
+ library.book.issue
+
+
+
+ Book issues
+ library.book.issue
+ ISSUE
+ 3
+
+
+ Card Details
+ library.card
+ tree,form
+ [('have_valid_card','=','True')]
+
+
+ library.card.tree
+ library.card
+
+
+
+
+
+
+
+
+
+
+ library.validity.form
+ library.validity
+
+
+
+
+
+ library.validity.tree
+ library.validity
+
+
+
+
+
+
+
+
+
+ Validity
+ library.validity
+
+
+ Book category
+ library.validity
+ VAL
+ 3
+
+
+ Validity
+ ir.actions.act_window
+ library.validity
+ form
+ tree,form
+
+
+
+
+ library.card.form
+ library.card
+
+
+
+
+
+ Library Card No
+ library.card
+
+
+
+ Library Card No
+ library.card
+ C
+ 1
+ 3
+
+
+ Book Reports
+ ir.actions.act_window
+ book.report
+ tree,form
+
+
+ book report
+ book.report
+ form
+
+
+
+
+
+
+
+ Available Books
+ ir.actions.act_window
+ product.product
+ tree
+ tree
+ [('available_copies','>',0)]
+
+
+ Book Holdings
+ ir.actions.act_window
+ library.book.issue
+ tree
+ tree
+ [('state','=','transfered')]
+
+
+ product.product.form
+ product.product
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ product.product.tree
+ product.product
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ product.product.tree
+ product.product
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library_management/view/registration.xml b/library_management/view/registration.xml
new file mode 100644
index 000000000..a92a9eb68
--- /dev/null
+++ b/library_management/view/registration.xml
@@ -0,0 +1,130 @@
+
+
+
+
+ Librarian group
+
+
+ Librarian
+
+
+
+ Administrator
+
+
+
+
+
+
+
+
+ Reg Number
+ reg.no
+
+
+
+ Reg Number
+ reg.no
+ R
+ 3
+
+
+
+
+ Registered users Manager
+
+
+ 1
+ days
+ -1
+
+ library.registration
+ _registered_user_manager
+ ()
+
+
+
+
+ Library Reminder
+
+
+ 1
+ days
+ -1
+
+ library.book.issue
+ _library_reminder
+ ()
+
+
+
+
+ library.registration.form.1
+ library.registration
+
+
+
+
+
+
+ library.registration.tree.1
+ library.registration
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library_management/view/report_invoice.xml b/library_management/view/report_invoice.xml
new file mode 100644
index 000000000..ec4f686af
--- /dev/null
+++ b/library_management/view/report_invoice.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Invoice
+
+
+
+
+
+
+
+
+ Book |
+ Description |
+ Quantity |
+ Unit Price |
+ Amount |
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library_management/view/user_view.xml b/library_management/view/user_view.xml
new file mode 100644
index 000000000..c87571e56
--- /dev/null
+++ b/library_management/view/user_view.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+ Registration Form
+ library.registration
+ form
+
+ tree,form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Members
+ res.partner
+ ir.actions.act_window
+ form
+ tree,form
+ [('librarian','=','True')]
+
+
+
+