[MERGE] Merged lp:openobject-addons

bzr revid: psa@tinyerp.com-20130925082318-253ageephv3s49ut
This commit is contained in:
Paramjit Singh Sahota 2013-09-25 13:53:18 +05:30
commit 1b0ad68d7a
37 changed files with 751 additions and 132 deletions

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-03-21 19:22+0000\n"
"Last-Translator: Liuming <gumdam20@me.com>\n"
"PO-Revision-Date: 2013-09-24 02:46+0000\n"
"Last-Translator: DWXXX <Unknown>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-12 06:40+0000\n"
"X-Generator: Launchpad (build 16761)\n"
"X-Launchpad-Export-Date: 2013-09-25 05:28+0000\n"
"X-Generator: Launchpad (build 16771)\n"
#. module: account_test
#: view:accounting.assert.test:0
@ -106,7 +106,7 @@ msgstr ""
#. module: account_test
#: view:accounting.assert.test:0
msgid "Description"
msgstr ""
msgstr "描述"
#. module: account_test
#: model:accounting.assert.test,desc:account_test.account_test_06_1
@ -123,13 +123,13 @@ msgstr ""
#: model:ir.actions.report.xml,name:account_test.account_assert_test_report
#: model:ir.ui.menu,name:account_test.menu_action_license
msgid "Accounting Tests"
msgstr ""
msgstr "帐户测试"
#. module: account_test
#: code:addons/account_test/report/account_test_report.py:74
#, python-format
msgid "The test was passed successfully"
msgstr ""
msgstr "测试通过"
#. module: account_test
#: field:accounting.assert.test,active:0
@ -155,7 +155,7 @@ msgstr ""
#. module: account_test
#: field:accounting.assert.test,code_exec:0
msgid "Python code"
msgstr ""
msgstr "Python代码"
#. module: account_test
#: model:accounting.assert.test,desc:account_test.account_test_07
@ -209,7 +209,7 @@ msgstr ""
#. module: account_test
#: view:accounting.assert.test:0
msgid "Python Code"
msgstr ""
msgstr "Python代码"
#. module: account_test
#: model:ir.actions.act_window,help:account_test.action_accounting_assert

View File

@ -0,0 +1,279 @@
# Chinese (Traditional) translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-09-19 09:40+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-20 05:38+0000\n"
"X-Generator: Launchpad (build 16765)\n"
#. module: auth_signup
#: field:res.partner,signup_type:0
msgid "Signup Token Type"
msgstr ""
#. module: auth_signup
#: field:base.config.settings,auth_signup_uninvited:0
msgid "Allow external users to sign up"
msgstr "允許外部使用者註冊"
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:19
#, python-format
msgid "Confirm Password"
msgstr "確認密碼"
#. module: auth_signup
#: help:base.config.settings,auth_signup_uninvited:0
msgid "If unchecked, only invited users may sign up."
msgstr "如果未勾選,只有被邀請的使用者可以註冊"
#. module: auth_signup
#: model:ir.model,name:auth_signup.model_base_config_settings
msgid "base.config.settings"
msgstr ""
#. module: auth_signup
#: code:addons/auth_signup/res_users.py:266
#, python-format
msgid "Cannot send email: user has no email address."
msgstr "無法送出email使用者沒有email 地址"
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:27
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:31
#, python-format
msgid "Reset password"
msgstr "重設密碼"
#. module: auth_signup
#: field:base.config.settings,auth_signup_template_user_id:0
msgid "Template user for new users created through signup"
msgstr ""
#. module: auth_signup
#: model:email.template,subject:auth_signup.reset_password_email
msgid "Password reset"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:120
#, python-format
msgid "Please enter a password and confirm it."
msgstr ""
#. module: auth_signup
#: view:res.users:0
msgid "Send an email to the user to (re)set their password."
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:26
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:29
#, python-format
msgid "Sign Up"
msgstr ""
#. module: auth_signup
#: selection:res.users,state:0
msgid "New"
msgstr ""
#. module: auth_signup
#: code:addons/auth_signup/res_users.py:258
#, python-format
msgid "Mail sent to:"
msgstr ""
#. module: auth_signup
#: field:res.users,state:0
msgid "Status"
msgstr ""
#. module: auth_signup
#: model:email.template,body_html:auth_signup.reset_password_email
msgid ""
"\n"
"<p>A password reset was requested for the OpenERP account linked to this "
"email.</p>\n"
"\n"
"<p>You may change your password by following <a "
"href=\"${object.signup_url}\">this link</a>.</p>\n"
"\n"
"<p>Note: If you do not expect this, you can safely ignore this email.</p>"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:114
#, python-format
msgid "Please enter a name."
msgstr ""
#. module: auth_signup
#: model:ir.model,name:auth_signup.model_res_users
msgid "Users"
msgstr ""
#. module: auth_signup
#: field:res.partner,signup_url:0
msgid "Signup URL"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:117
#, python-format
msgid "Please enter a username."
msgstr ""
#. module: auth_signup
#: selection:res.users,state:0
msgid "Active"
msgstr ""
#. module: auth_signup
#: code:addons/auth_signup/res_users.py:270
#, python-format
msgid ""
"Cannot send email: no outgoing email server configured.\n"
"You can configure it under Settings/General Settings."
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:12
#, python-format
msgid "Username"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:8
#, python-format
msgid "Name"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:173
#, python-format
msgid "Please enter a username or email address."
msgstr ""
#. module: auth_signup
#: selection:res.users,state:0
msgid "Resetting Password"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:13
#, python-format
msgid "Username (Email)"
msgstr ""
#. module: auth_signup
#: field:res.partner,signup_expiration:0
msgid "Signup Expiration"
msgstr ""
#. module: auth_signup
#: help:base.config.settings,auth_signup_reset_password:0
msgid "This allows users to trigger a password reset from the Login page."
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:25
#, python-format
msgid "Log in"
msgstr ""
#. module: auth_signup
#: field:res.partner,signup_valid:0
msgid "Signup Token is Valid"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:111
#: code:addons/auth_signup/static/src/js/auth_signup.js:114
#: code:addons/auth_signup/static/src/js/auth_signup.js:117
#: code:addons/auth_signup/static/src/js/auth_signup.js:120
#: code:addons/auth_signup/static/src/js/auth_signup.js:123
#: code:addons/auth_signup/static/src/js/auth_signup.js:170
#: code:addons/auth_signup/static/src/js/auth_signup.js:173
#, python-format
msgid "Login"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:97
#, python-format
msgid "Invalid signup token"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:123
#, python-format
msgid "Passwords do not match; please retype them."
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/js/auth_signup.js:111
#: code:addons/auth_signup/static/src/js/auth_signup.js:170
#, python-format
msgid "No database selected !"
msgstr ""
#. module: auth_signup
#: view:res.users:0
msgid "Reset Password"
msgstr ""
#. module: auth_signup
#: field:base.config.settings,auth_signup_reset_password:0
msgid "Enable password reset from Login page"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:30
#, python-format
msgid "Back to Login"
msgstr ""
#. module: auth_signup
#. openerp-web
#: code:addons/auth_signup/static/src/xml/auth_signup.xml:22
#, python-format
msgid "Sign up"
msgstr ""
#. module: auth_signup
#: model:ir.model,name:auth_signup.model_res_partner
msgid "Partner"
msgstr ""
#. module: auth_signup
#: field:res.partner,signup_token:0
msgid "Signup Token"
msgstr ""

View File

@ -298,7 +298,7 @@ class crm_lead(format_address, osv.osv):
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
'color': 0,
'date_last_stage_update': fields.datetime.now(),
'date_last_stage_update': fields.datetime.now,
}
_sql_constraints = [

View File

@ -108,7 +108,7 @@ class crm_claim(osv.osv):
_defaults = {
'user_id': lambda s, cr, uid, c: uid,
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
'date': fields.datetime.now(),
'date': fields.datetime.now,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
'active': lambda *a: 1,

View File

@ -80,7 +80,7 @@ class crm_helpdesk(osv.osv):
'active': lambda *a: 1,
'user_id': lambda s, cr, uid, c: uid,
'state': lambda *a: 'draft',
'date': lambda *a: fields.datetime.now(),
'date': fields.datetime.now,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
}

File diff suppressed because one or more lines are too long

View File

@ -225,7 +225,7 @@ class hr_applicant(osv.Model):
'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c),
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'hr.applicant', context=c),
'color': 0,
'date_last_stage_update': fields.datetime.now(),
'date_last_stage_update': fields.datetime.now,
}
_group_by_full = {

View File

@ -303,7 +303,7 @@ class im_user(osv.osv):
'name': fields.function(_get_name, type='char', size=200, string="Name", store=True, readonly=True),
'assigned_name': fields.char(string="Assigned Name", size=200, required=False),
'image': fields.related('user_id', 'image_small', type='binary', string="Image", readonly=True),
'user_id': fields.many2one("res.users", string="User", select=True, ondelete='cascade'),
'user_id': fields.many2one("res.users", string="User", select=True, ondelete='cascade', oldname='user'),
'uuid': fields.char(string="UUID", size=50, select=True),
'im_last_received': fields.integer(string="Instant Messaging Last Received Message"),
'im_last_status': fields.boolean(strint="Instant Messaging Last Status"),

View File

@ -212,7 +212,7 @@ class mail_message(osv.Model):
_defaults = {
'type': 'email',
'date': fields.datetime.now(),
'date': fields.datetime.now,
'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx),
'body': '',
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),

View File

@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-18 04:49+0000\n"
"X-Launchpad-Export-Date: 2013-09-19 04:42+0000\n"
"X-Generator: Launchpad (build 16765)\n"
#. module: marketing_campaign

View File

@ -21,7 +21,11 @@
{
'name': 'Mass Mailing Campaigns',
'description': """TODO""",
'description': """
Easily send mass mailing to your leads, opportunities or customers. Track
marketing campaigns performance to improve conversion rates. Design
professional emails and reuse templates in a few clicks.
""",
'version': '1.0',
'author': 'OpenERP',
'website': 'http://www.openerp.com',

View File

@ -274,7 +274,7 @@ class MassMailing(osv.Model):
}
_defaults = {
'date': fields.datetime.now(),
'date': fields.datetime.now,
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -0,0 +1,227 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Mass Mailing Made Easy</h2>
<h3 class="oe_slogan">Design, Send, Track Emails</h3>
<div class="oe_span6">
<div class="oe_bg_img">
<img src="mass_mailing_campaign.png" class="oe_picture oe_screenshot">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
Easily send mass mailing to your leads, opportunities or customers. Track
marketing campaigns performance to improve conversion rates. Design
professional emails and reuse templates in a few clicks.
</p>
<div class="oe_centeralign oe_websiteonly">
<a href="http://www.openerp.com/start" class="oe_button oe_big oe_tacky">Start your <span class="oe_emph">free</span> trial</a>
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row">
<h2 class="oe_slogan">Send Professional Emails</h2>
<div class="oe_span6">
<p class='oe_mt32'>
Import database of prospects or filter on
existing leads, opportunities and customers in just a few clicks.
</p><p>
Define email templates to reuse content or specific design for your newsletter.
Setup several email servers with their own IP/domain to optimise opening rates.
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img class="oe_picture oe_screenshot" src="mass_mailing_composer.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row">
<h2 class="oe_slogan">Organize Marketing Campaigns</h2>
<h3 class="oe_slogan">Design, Send, Track by Campaigns</h3>
<div class="oe_span6">
<div class="oe_bg_img">
<img class="oe_picture oe_screenshot" src="mass_mailing_campaign.png">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
Get real time statistics on campaigns performance to improve your
conversion rate. Track mails sent, received, opened and
answered.
</p><p>
Easily manage your marketing campaigns, discussion groups,
leads and opportunities in one simple and powerful platform.
</p>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row">
<h2 class="oe_slogan">Integrated with OpenERP Apps</h2>
<h2 class="oe_slogan"></h2>
<div class="oe_span6">
<p class='oe_mt32'>
Get access to mass mailing features from every OpenERP app to improve
the way your users communicate.
</p><p>
Send template of emails from <a href="/apps/crm">CRM</a> opportunities, select leads based on
marketing segments, send <a href="/apps/hr_recruitment">jobs offers</a> and automate answers to applicants, reuse
email template in the <a href="/apps/marketing_campaign">lead automation marketing campaigns</a>.
</p><p>
Answers to your emails appears automatically in the history of every document with the
<a href="/apps/mail">social network</a> module.
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img class="oe_picture oe_screenshot" src="mass_mailing_tasks.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row">
<h2 class="oe_slogan">Clean Your Lead Database</h2>
<h3 class="oe_slogan">Handle bounce and conversion rates</h3>
<div class="oe_span6">
<div class="oe_bg_img">
<img class="oe_picture oe_screenshot" src="mass_mailing_mailing.png">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
Get a clean lead database that improves over the time using the
performance of your mails. OpenERP handle bounce mails
efficiently, flag erroneous leads accordingly and gives you
statistics on the quality of your leads.
</p>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row">
<h2 class="oe_slogan">One click emails send</h2>
<h3 class="oe_slogan">Select any documents, send emails</h3>
<div class="oe_span6">
<p class='oe_mt32'>
The marketing department will love working on campaigns. But you can also
give a one click mass mailing facility to all others users on their own
prospects or documents.
</p><p>
Select a few documents (e.g. leads, support tickets, suppliers, applicants,
...) and send emails to their contacts in one click, reusing existing emails
templates.
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img class="oe_picture oe_screenshot" src="mass_mailing_composer.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row">
<h2 class="oe_slogan">Follow-up On Answers</h2>
<h3 class="oe_slogan">Communicate efficiently with prospects</h3>
<div class="oe_span6">
<div class="oe_bg_img">
<img class="oe_picture oe_screenshot" src="mass_mailing_history.png">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
The chatter feature enables you to communicate faster and more efficiently with
your customer. Get documents created automatically (leads, opportunities,
tasks, ...) based on answers to your mass mailing campaigns Follow the
discussion directly on the business documents within OpenERP or via email.
</p><p>
Get all the negotiations and discussions attached to the right document
and relevent managers notified on specific events.
</p>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Campaigns Dashboard</h2>
<h3 class="oe_slogan">Analyse the performance of your campaigns</h3>
<div class="oe_span6">
<p class="oe_mt32">
Get the insights you need to make smarter marketing campaign. Track statistics
per campaign: bounce rates, sent mails, best content, etc. The clear dashboards
gives you a direct overview of your campaign performance.
</p>
</div>
<div class="oe_span6">
<div class="oe_bg_img">
<img class="oe_picture oe_screenshot" src="mass_mailing_dashboard.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row">
<h2 class="oe_slogan">Fully Integrated With Others Apps</h2>
<h3 class="oe_slogan">Efficient mailing for every users</h3>
</div>
<div class="oe_row">
<div class="oe_span4">
<a href="/apps/marketing_campaign">
<h3>Lead Automation</h3>
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="app_marketing_campaign.png">
</div>
</a>
<p>
Define automated actions (e.g. ask a salesperson to call, send
an email, ...) based on triggers (no activity since 20 days,
answered a promotional email, etc.)
</p><p>
Optimize campaigns from lead to close, on every channel. Make
smarter decisions about where to invest and show the impact of
your marketing activities on your company's bottom line.
</p>
</div>
<div class="oe_span4">
<a href="/apps/website_crm">
<h3>Website Forms</h3>
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="app_website_crm.png">
</div>
</a>
<p>
Integrate a contact form in your website easily. Forms
submissions create leads automatically in OpenERP CRM. Leads
can be used in marketing campaigns.
</p>
</div>
<div class="oe_span4">
<a href="/apps/crm">
<h3>CRM</h3>
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot" src="app_crm.png">
</div>
</a>
<p>
Manage your sales funnel with no effort. Attract leads, follow-up on phone
calls and meetings. Analyse the quality of your leads to make informed
decisions and save time by integrating emails directly into the application.
</p>
</div>
</div>
</section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -82,7 +82,7 @@ class PointOfSaleController(http.Controller):
"""
print 'scan_item_success: ' + str(ean)
@http.route('/pos/scan_item_error_unrecognized')
@http.route('/pos/scan_item_error_unrecognized', type='json', auth='admin')
def scan_item_error_unrecognized(self, ean):
"""
A product has been scanned without success

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

View File

@ -43,6 +43,7 @@ function openerp_pos_db(instance, module){
this.product_by_id = {};
this.product_by_ean13 = {};
this.product_by_category_id = {};
this.product_by_reference = {};
this.category_by_id = {};
this.root_category_id = 0;
@ -197,6 +198,9 @@ function openerp_pos_db(instance, module){
if(product.ean13){
this.product_by_ean13[product.ean13] = product;
}
if(product.default_code){
this.product_by_reference[product.default_code] = product;
}
}
},
add_packagings: function(packagings){
@ -241,6 +245,9 @@ function openerp_pos_db(instance, module){
}
return undefined;
},
get_product_by_reference: function(ref){
return this.product_by_reference[ref];
},
get_product_by_category: function(category_id){
var product_ids = this.product_by_category_id[category_id];
var list = [];

View File

@ -450,7 +450,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
// it will check its validity then return an object containing various
// information about the ean.
// most importantly :
// - ean : the ean
// - code : the ean
// - type : the type of the ean:
// 'price' | 'weight' | 'unit' | 'cashier' | 'client' | 'discount' | 'error'
//
@ -460,13 +460,16 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
// - unit : if the encoded value has a unit, it will be put there.
// not to be confused with the 'unit' type, which represent an unit of a
// unique product
// - base_code : the ean code with all the encoding parts set to zero; the one put on
// the product in the backend
parse_ean: function(ean){
var parse_result = {
type:'unknown', //
encoding: 'ean13',
type:'unknown',
prefix:'',
ean:ean,
base_ean: ean,
code:ean,
base_code: ean,
id:'',
value: 0,
unit: 'none',
@ -487,13 +490,13 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
parse_result.type = 'error';
} else if( match_prefix(this.price_prefix_set,'price')){
parse_result.id = ean.substring(0,7);
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
parse_result.base_code = this.sanitize_ean(ean.substring(0,7));
parse_result.value = Number(ean.substring(7,12))/100.0;
parse_result.unit = 'euro';
} else if( match_prefix(this.weight_prefix_set,'weight')){
parse_result.id = ean.substring(0,7);
parse_result.value = Number(ean.substring(7,12))/1000.0;
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
parse_result.base_code = this.sanitize_ean(ean.substring(0,7));
parse_result.unit = 'Kg';
} else if( match_prefix(this.client_prefix_set,'client')){
parse_result.id = ean.substring(0,7);
@ -502,7 +505,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
parse_result.id = ean.substring(0,7);
} else if( match_prefix(this.discount_prefix_set,'discount')){
parse_result.id = ean.substring(0,7);
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
parse_result.base_code = this.sanitize_ean(ean.substring(0,7));
parse_result.value = Number(ean.substring(7,12))/100.0;
parse_result.unit = '%';
} else {
@ -512,9 +515,18 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
}
return parse_result;
},
on_ean: function(ean){
var parse_result = this.parse_ean(ean);
scan: function(type,code){
if (type === 'ean13'){
var parse_result = this.parse_ean(code);
}else if(type === 'reference'){
var parse_result = {
encoding: 'reference',
type: 'unit',
code: code,
prefix: '',
};
}
if (parse_result.type === 'error') { //most likely a checksum error, raise warning
console.warn('WARNING: barcode checksum error:',parse_result);
@ -522,7 +534,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
if(this.action_callback['product']){
this.action_callback['product'](parse_result);
}
//this.trigger("codebar",parse_result );
}else{
if(this.action_callback[parse_result.type]){
this.action_callback[parse_result.type](parse_result);
@ -530,49 +541,63 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
}
},
on_reference: function(code){
if(this.action_callback['reference']){
this.action_callback['reference'](code);
}
},
// starts catching keyboard events and tries to interpret codebar
// calling the callbacks when needed.
connect: function(){
var self = this;
var codeNumbers = [];
var timeStamp = 0;
var lastTimeStamp = 0;
var code = "";
var timeStamp = 0;
var onlynumbers = true;
var timeout = null;
// The barcode readers acts as a keyboard, we catch all keyup events and try to find a
// barcode sequence in the typed keys, then act accordingly.
$('body').delegate('','keypress', function (e){
//console.log('keyup:'+String.fromCharCode(e.keyCode)+' '+e.keyCode,e);
//We only care about numbers
if (e.keyCode >= 48 && e.keyCode < 58){
this.handler = function(e){
// The barcode reader sends keystrokes with a specific interval.
// We look if the typed keys fit in the interval.
if (codeNumbers.length === 0) {
timeStamp = new Date().getTime();
} else {
if (lastTimeStamp + 30 < new Date().getTime()) {
// not a barcode reader
codeNumbers = [];
timeStamp = new Date().getTime();
}
}
codeNumbers.push(e.keyCode - 48);
lastTimeStamp = new Date().getTime();
if (codeNumbers.length === 13) {
//We have found what seems to be a valid codebar
self.on_ean(codeNumbers.join(''));
codeNumbers = [];
}
} else {
// NaN
codeNumbers = [];
if(e.which === 13){ //ignore returns
return;
}
});
if(timeStamp + 50 < new Date().getTime()){
code = "";
onlynumbers = true;
}
timeStamp = new Date().getTime();
clearTimeout(timeout);
if( e.which < 48 || e.which >= 58 ){ // not a number
onlynumbers = false;
}
code += String.fromCharCode(e.which);
// we wait for a while after the last input to be sure that we are not mistakingly
// returning a code which is a prefix of a bigger one :
// Internal Ref 5449 vs EAN13 5449000...
timeout = setTimeout(function(){
if(code.length === 13 && onlynumbers){
self.scan('ean13',code);
}else if(code.length >= 3 && self.pos.db.get_product_by_reference(code)){
self.scan('reference',code);
}
code = "";
onlynumbers = true;
},100);
};
$('body').on('keypress', this.handler);
},
// stops catching keyboard events
disconnect: function(){
$('body').undelegate('', 'keyup')
$('body').off('keypress', this.handler)
},
});

View File

@ -52,6 +52,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
'pos_config': null,
'units': null,
'units_by_id': null,
'pricelist': null,
'selectedOrder': null,
});
@ -113,10 +114,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
}).then(function(company_partners){
self.get('company').contact_address = company_partners[0].contact_address;
return self.fetch('res.currency',['symbol','position','rounding','accuracy'],[['id','=',self.get('company').currency_id[0]]]);
}).then(function(currencies){
self.set('currency',currencies[0]);
return self.fetch('product.uom', null, null);
}).then(function(units){
self.set('units',units);
@ -172,6 +169,14 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
}).then(function(shops){
self.set('shop',shops[0]);
return self.fetch('product.pricelist',['currency_id'],[['id','=',self.get('pos_config').pricelist_id[0]]]);
}).then(function(pricelists){
self.set('pricelist',pricelists[0]);
return self.fetch('res.currency',['symbol','position','rounding','accuracy'],[['id','=',self.get('pricelist').currency_id[0]]]);
}).then(function(currencies){
self.set('currency',currencies[0]);
return self.fetch('product.packaging',['ean','product_id']);
}).then(function(packagings){
self.db.add_packagings(packagings);
@ -185,7 +190,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
['name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'default_code',
'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description'],
[['sale_ok','=',true],['available_in_pos','=',true]],
{pricelist: self.get('pos_config').pricelist_id[0]} // context for price
{pricelist: self.get('pricelist').id} // context for price
);
}).then(function(products){
self.db.add_products(products);
@ -423,19 +428,23 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
return tried_all;
},
scan_product: function(parsed_ean){
scan_product: function(parsed_code){
var self = this;
var product = this.db.get_product_by_ean13(parsed_ean.base_ean);
var selectedOrder = this.get('selectedOrder');
if(parsed_code.encoding === 'ean13'){
var product = this.db.get_product_by_ean13(parsed_code.base_code);
}else if(parsed_code.encoding === 'reference'){
var product = this.db.get_product_by_reference(parsed_code.code);
}
if(!product){
return false;
}
if(parsed_ean.type === 'price'){
selectedOrder.addProduct(new module.Product(product), {price:parsed_ean.value});
}else if(parsed_ean.type === 'weight'){
selectedOrder.addProduct(new module.Product(product), {quantity:parsed_ean.value, merge:false});
if(parsed_code.type === 'price'){
selectedOrder.addProduct(new module.Product(product), {price:parsed_code.value});
}else if(parsed_code.type === 'weight'){
selectedOrder.addProduct(new module.Product(product), {quantity:parsed_code.value, merge:false});
}else{
selectedOrder.addProduct(new module.Product(product));
}

View File

@ -160,29 +160,29 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
// what happens when a product is scanned :
// it will add the product to the order and go to barcode_product_screen. Or show barcode_product_error_popup if
// there's an error.
barcode_product_action: function(ean){
barcode_product_action: function(code){
var self = this;
if(self.pos.scan_product(ean)){
self.pos.proxy.scan_item_success(ean);
if(self.pos.scan_product(code)){
self.pos.proxy.scan_item_success(code);
if(self.barcode_product_screen){
self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen);
}
}else{
self.pos.proxy.scan_item_error_unrecognized(ean);
self.pos.proxy.scan_item_error_unrecognized(code);
if(self.barcode_product_error_popup && self.pos_widget.screen_selector.get_user_mode() !== 'cashier'){
self.pos_widget.screen_selector.show_popup(self.barcode_product_error_popup);
}
}
},
// what happens when a cashier id barcode is scanned.
// the default behavior is the following :
// - if there's a user with a matching ean, put it as the active 'cashier', go to cashier mode, and return true
// - else : do nothing and return false. You probably want to extend this to show and appropriate error popup...
barcode_cashier_action: function(ean){
barcode_cashier_action: function(code){
var users = this.pos.get('user_list');
for(var i = 0, len = users.length; i < len; i++){
if(users[i].ean13 === ean.ean){
if(users[i].ean13 === code.code){
this.pos.set('cashier',users[i]);
this.pos_widget.username.refresh();
this.pos.proxy.cashier_mode_activated();
@ -190,7 +190,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
return true;
}
}
this.pos.proxy.scan_item_error_unrecognized(ean);
this.pos.proxy.scan_item_error_unrecognized(code);
return false;
},
@ -198,28 +198,28 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
// the default behavior is the following :
// - if there's a user with a matching ean, put it as the active 'client' and return true
// - else : return false.
barcode_client_action: function(ean){
barcode_client_action: function(code){
var partners = this.pos.get('partner_list');
for(var i = 0, len = partners.length; i < len; i++){
if(partners[i].ean13 === ean.ean){
if(partners[i].ean13 === code.code){
this.pos.get('selectedOrder').set_client(partners[i]);
this.pos_widget.username.refresh();
this.pos.proxy.scan_item_success(ean);
this.pos.proxy.scan_item_success(code);
return true;
}
}
this.pos.proxy.scan_item_error_unrecognized(ean);
this.pos.proxy.scan_item_error_unrecognized(code);
return false;
//TODO start the transaction
},
// what happens when a discount barcode is scanned : the default behavior
// is to set the discount on the last order.
barcode_discount_action: function(ean){
this.pos.proxy.scan_item_success(ean);
barcode_discount_action: function(code){
this.pos.proxy.scan_item_success(code);
var last_orderline = this.pos.get('selectedOrder').getLastOrderline();
if(last_orderline){
last_orderline.set_discount(ean.value)
last_orderline.set_discount(code.value)
}
},
@ -292,10 +292,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.pos_widget.username.set_user_mode(this.pos_widget.screen_selector.get_user_mode());
this.pos.barcode_reader.set_action_callback({
'cashier': self.barcode_cashier_action ? function(ean){ self.barcode_cashier_action(ean); } : undefined ,
'product': self.barcode_product_action ? function(ean){ self.barcode_product_action(ean); } : undefined ,
'client' : self.barcode_client_action ? function(ean){ self.barcode_client_action(ean); } : undefined ,
'discount': self.barcode_discount_action ? function(ean){ self.barcode_discount_action(ean); } : undefined,
'cashier': self.barcode_cashier_action ? function(code){ self.barcode_cashier_action(code); } : undefined ,
'product': self.barcode_product_action ? function(code){ self.barcode_product_action(code); } : undefined ,
'client' : self.barcode_client_action ? function(code){ self.barcode_client_action(code); } : undefined ,
'discount': self.barcode_discount_action ? function(code){ self.barcode_discount_action(code); } : undefined,
});
},
@ -405,7 +405,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.pos.barcode_reader.save_callbacks();
this.pos.barcode_reader.reset_action_callbacks();
this.pos.barcode_reader.set_action_callback({
'cashier': function(ean){
'cashier': function(code){
clearInterval(this.intervalID);
self.pos.proxy.cashier_mode_activated();
self.pos_widget.screen_selector.set_user_mode('cashier');
@ -683,14 +683,14 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
show_numpad: false,
show_leftpane: false,
barcode_product_action: function(ean){
barcode_product_action: function(code){
this.pos.proxy.transaction_start();
this._super(ean);
this._super(code);
},
barcode_client_action: function(ean){
barcode_client_action: function(code){
this.pos.proxy.transaction_start();
this._super(ean);
this._super(code);
$('.goodbye-message').addClass('oe_hidden');
this.pos_widget.screen_selector.show_popup('choose-receipt');
},
@ -883,6 +883,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
label: _t('Back'),
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
click: function(){
_.each(self.paymentlinewidgets, function(widget){
if( widget.payment_line.get_amount() === 0 ){
widget.payment_line.destroy();
}
});
self.pos_widget.screen_selector.set_current_screen(self.back_screen);
},
});

View File

@ -43,10 +43,15 @@ function openerp_pos_keyboard(instance, module){ //module is instance.point_of_s
// Write a character to the input zone
writeCharacter: function(character){
var $input = this.$target
$input[0].value += character;
$input.keydown();
$input.keyup();
var $input = this.$target;
if(character === '\n'){
$input.trigger($.Event('keydown',{which:13}));
$input.trigger($.Event('keyup',{which:13}));
}else{
$input[0].value += character;
$input.keydown();
$input.keyup();
}
},
// Sends a 'return' character to the input zone. TODO

View File

@ -516,7 +516,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
var cat = self.pos.db.get_category_by_id(id);
self.set_category(cat);
self.renderElement();
self.search_and_categories(cat);
});
});
// breadcrumb click actions
@ -525,12 +524,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
var category = self.pos.db.get_category_by_id(id);
self.set_category(category);
self.renderElement();
self.search_and_categories(category);
});
this.search_and_categories();
if(this.pos.iface_vkeyboard && this.pos_widget.onscreen_keyboard){
this.pos_widget.onscreen_keyboard.connect(this.$('.searchbox input'));
}
this.search_and_categories();
},
set_product_type: function(type){ // 'all' | 'weightable'
@ -542,7 +542,14 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
reset_category: function(){
this.set_category();
this.renderElement();
this.search_and_categories();
},
// empties the content of the search box
clear_search: function(){
var products = this.pos.db.get_product_by_category(this.category.id);
this.pos.get('products').reset(products);
this.$('.searchbox input').val('').focus();
this.$('.search-clear').fadeOut();
},
// filters the products, and sets up the search callbacks
@ -554,12 +561,20 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
self.pos.get('products').reset(products);
// filter the products according to the search string
this.$('.searchbox input').keyup(function(){
this.$('.searchbox input').keyup(function(event){
console.log('event',event);
query = $(this).val().toLowerCase();
if(query){
var products = self.pos.db.search_product_in_category(self.category.id, query);
self.pos.get('products').reset(products);
self.$('.search-clear').fadeIn();
if(event.which === 13){
if( self.pos.get('products').size() === 1 ){
self.pos.get('selectedOrder').addProduct(self.pos.get('products').at(0));
self.clear_search();
}
}else{
var products = self.pos.db.search_product_in_category(self.category.id, query);
self.pos.get('products').reset(products);
self.$('.search-clear').fadeIn();
}
}else{
var products = self.pos.db.get_product_by_category(self.category.id);
self.pos.get('products').reset(products);
@ -567,14 +582,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
}
});
this.$('.searchbox input').click(function(){}); //Why ???
//reset the search when clicking on reset
this.$('.search-clear').click(function(){
var products = self.pos.db.get_product_by_category(self.category.id);
self.pos.get('products').reset(products);
self.$('.searchbox input').val('').focus();
self.$('.search-clear').fadeOut();
self.clear_search();
});
},
});
@ -668,7 +678,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
var self = this;
this._super();
if(this.action){
this.$el.click(function(){ self.action(); });
this.$el.click(function(){
self.action();
});
}
},
show: function(){ this.$el.removeClass('oe_hidden'); },
@ -732,12 +744,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.$('.button.custom_ean').click(function(){
var ean = self.pos.barcode_reader.sanitize_ean(self.$('input.ean').val() || '0');
self.$('input.ean').val(ean);
self.pos.barcode_reader.on_ean(ean);
self.pos.barcode_reader.scan('ean13',ean);
});
this.$('.button.reference').click(function(){
self.pos.barcode_reader.scan('reference',self.$('input.ean').val());
});
_.each(this.eans, function(ean, name){
self.$('.button.'+name).click(function(){
self.$('input.ean').val(ean);
self.pos.barcode_reader.on_ean(ean);
self.pos.barcode_reader.scan('ean13',ean);
});
});
_.each(this.events, function(name){
@ -1082,15 +1097,29 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
},
close: function() {
var self = this;
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe(
_.bind(function(res) {
return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) {
var action = result;
action.context = _.extend(action.context || {}, {'cancel_action': {type: 'ir.actions.client', tag: 'reload'}});
//self.destroy();
this.do_action(action);
}, this));
}, this));
function close(){
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe(
_.bind(function(res) {
return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) {
var action = result;
action.context = _.extend(action.context || {}, {'cancel_action': {type: 'ir.actions.client', tag: 'reload'}});
//self.destroy();
this.do_action(action);
}, this));
}, self));
}
var draft_order = _.find( self.pos.get('orders').models, function(order){
return order.get('orderLines').length !== 0 && order.get('paymentLines').length === 0;
});
if(draft_order){
if (confirm(_t("Pending orders will be lost.\nAre you sure you want to leave this session?"))) {
return close();
}
}else{
return close();
}
},
destroy: function() {
this.pos.destroy();

View File

@ -12,8 +12,8 @@
</div>
<div id="rightheader">
<div id="order-selector">
<button class="neworder-button square"></button>
<button class="deleteorder-button square"></button>
<button class="neworder-button square"><img src='/point_of_sale/static/src/img/plus.png' /></button>
<button class="deleteorder-button square"><img src='/point_of_sale/static/src/img/minus.png' /></button>
<ol id="orders"></ol>
</div>
<!-- here goes header buttons -->
@ -494,6 +494,7 @@
<li class="button lemon_price">1.54€ Lemon</li>
<li class="button unknown_product">Unknown Product</li>
<li class="button invalid_ean">Invalid Ean</li>
<li class="button reference">Reference</li>
</ul>
<p class="category">Hardware Status</p>

View File

@ -15,7 +15,7 @@
<field name="pos_state" invisible="1" />
</group>
<field name="pos_session_id" invisible="1"/>
<button name="open_ui" type="object" string="Start Selling"
<button name="open_ui" type="object" string="Resume Session"
attrs="{'invisible' : [('pos_state', 'not in', ('opened',))]}"
class="oe_highlight"
/>

View File

@ -0,0 +1,25 @@
# Croatian translation for openobject-addons
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2013-09-19 13:17+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Croatian <hr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-09-20 05:38+0000\n"
"X-Generator: Launchpad (build 16765)\n"
#. module: portal_anonymous
#. openerp-web
#: code:addons/portal_anonymous/static/src/xml/portal_anonymous.xml:8
#, python-format
msgid "Login"
msgstr "Prijava"

View File

@ -804,7 +804,7 @@ class task(osv.osv):
_defaults = {
'stage_id': _get_default_stage_id,
'project_id': _get_default_project_id,
'date_last_stage_update': lambda *a: fields.datetime.now(),
'date_last_stage_update': fields.datetime.now,
'kanban_state': 'normal',
'priority': '2',
'progress': 0,

View File

@ -297,7 +297,7 @@ class project_issue(osv.Model):
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
'priority': crm.AVAILABLE_PRIORITIES[2][0],
'kanban_state': 'normal',
'date_last_stage_update': fields.datetime.now(),
'date_last_stage_update': fields.datetime.now,
'user_id': lambda obj, cr, uid, context: uid,
}