Prateeksha Singh | 6495d53 | 2018-08-01 16:38:39 +0530 | [diff] [blame] | 1 | from __future__ import unicode_literals |
| 2 | import frappe, requests, json |
| 3 | from frappe.utils import now |
| 4 | from frappe.frappeclient import FrappeClient |
| 5 | |
| 6 | @frappe.whitelist() |
| 7 | def call_hub_method(method, params=None): |
| 8 | connection = get_hub_connection() |
| 9 | |
| 10 | if type(params) == unicode: |
| 11 | params = json.loads(params) |
| 12 | |
| 13 | params.update({ |
| 14 | 'cmd': 'hub.hub.api.' + method |
| 15 | }) |
| 16 | |
| 17 | response = connection.post_request(params) |
| 18 | return response |
| 19 | |
| 20 | |
| 21 | #### LOCAL ITEMS |
| 22 | @frappe.whitelist() |
| 23 | def get_valid_items(search_value=''): |
| 24 | items = frappe.get_list( |
| 25 | 'Item', |
| 26 | fields=["*"], |
| 27 | filters={ |
| 28 | 'item_name': ['like', '%' + search_value + '%'], |
| 29 | 'publish_in_hub': 0 |
| 30 | }, |
| 31 | order_by="modified desc" |
| 32 | ) |
| 33 | |
| 34 | valid_items = filter(lambda x: x.image and x.description, items) |
| 35 | |
| 36 | def attach_source_type(item): |
| 37 | item.source_type = "local" |
| 38 | return item |
| 39 | |
| 40 | valid_items = map(lambda x: attach_source_type(x), valid_items) |
| 41 | return valid_items |
| 42 | |
| 43 | @frappe.whitelist() |
| 44 | def publish_selected_items(items_to_publish): |
| 45 | items_to_publish = json.loads(items_to_publish) |
| 46 | if not len(items_to_publish): |
| 47 | return |
| 48 | |
| 49 | for item_code in items_to_publish: |
| 50 | frappe.db.set_value('Item', item_code, 'publish_in_hub', 1) |
| 51 | |
| 52 | try: |
| 53 | hub_settings = frappe.get_doc('Hub Settings') |
| 54 | item_sync_preprocess() |
| 55 | hub_settings.sync() |
| 56 | except Exception as e: |
| 57 | frappe.db.set_value("Hub Settings", "Hub Settings", "sync_in_progress", 0) |
| 58 | frappe.throw(e) |
| 59 | |
| 60 | def item_sync_preprocess(): |
| 61 | # Call Hub to make a new activity |
| 62 | # and return an activity ID |
| 63 | # that will be used as the remote ID for the Migration Run |
| 64 | |
| 65 | hub_seller = frappe.db.get_value("Hub Settings", "Hub Settings", "company_email") |
| 66 | |
| 67 | response = call_hub_method('add_hub_seller_activity', { |
| 68 | 'hub_seller': hub_seller, |
| 69 | 'activity_details': json.dumps({ |
| 70 | 'subject': 'Publishing items', |
| 71 | 'status': 'Success' |
| 72 | }) |
| 73 | }) |
| 74 | |
| 75 | if response: |
| 76 | frappe.db.set_value("Hub Settings", "Hub Settings", "sync_in_progress", 1) |
| 77 | return response |
| 78 | else: |
| 79 | frappe.throw('Unable to update remote activity') |
| 80 | |
| 81 | def item_sync_postprocess(sync_details): |
| 82 | hub_seller = frappe.db.get_value("Hub Settings", "Hub Settings", "company_email") |
| 83 | |
| 84 | response = call_hub_method('add_hub_seller_activity', { |
| 85 | 'hub_seller': hub_seller, |
| 86 | 'activity_details': json.dumps({ |
| 87 | 'subject': 'Publishing items:' + sync_details['status'], |
| 88 | 'content': json.dumps(sync_details['stats']) |
| 89 | }) |
| 90 | }) |
| 91 | |
| 92 | if response: |
| 93 | frappe.db.set_value('Hub Settings', 'Hub Settings', 'sync_in_progress', 0) |
| 94 | frappe.db.set_value('Hub Settings', 'Hub Settings', 'last_sync_datetime', frappe.utils.now()) |
| 95 | else: |
| 96 | frappe.throw('Unable to update remote activity') |
| 97 | |
| 98 | def get_hub_connection(): |
| 99 | if frappe.db.exists('Data Migration Connector', 'Hub Connector'): |
| 100 | hub_connector = frappe.get_doc('Data Migration Connector', 'Hub Connector') |
| 101 | hub_connection = hub_connector.get_connection() |
| 102 | return hub_connection.connection |
| 103 | |
| 104 | # read-only connection |
| 105 | hub_connection = FrappeClient(frappe.conf.hub_url) |
| 106 | return hub_connection |
| 107 | |
| 108 | |
| 109 | |
| 110 | # Legacy functionality |
| 111 | # ============================================================================= |
| 112 | |
| 113 | @frappe.whitelist() |
| 114 | def get_item_favourites(start=0, limit=20, fields=["*"], order_by=None): |
| 115 | doctype = 'Hub Item' |
| 116 | hub_settings = frappe.get_doc('Hub Settings') |
| 117 | item_names_str = hub_settings.get('custom_data') or '[]' |
| 118 | item_names = json.loads(item_names_str) |
| 119 | filters = json.dumps({ |
| 120 | 'hub_item_code': ['in', item_names] |
| 121 | }) |
| 122 | return get_list(doctype, start, limit, fields, filters, order_by) |
| 123 | |
| 124 | @frappe.whitelist() |
| 125 | def update_wishlist_item(item_name, remove=0): |
| 126 | remove = int(remove) |
| 127 | hub_settings = frappe.get_doc('Hub Settings') |
| 128 | data = hub_settings.get('custom_data') |
| 129 | if not data or not json.loads(data): |
| 130 | data = '[]' |
| 131 | hub_settings.custom_data = data |
| 132 | hub_settings.save() |
| 133 | |
| 134 | item_names_str = data |
| 135 | item_names = json.loads(item_names_str) |
| 136 | if not remove and item_name not in item_names: |
| 137 | item_names.append(item_name) |
| 138 | if remove and item_name in item_names: |
| 139 | item_names.remove(item_name) |
| 140 | |
| 141 | item_names_str = json.dumps(item_names) |
| 142 | |
| 143 | hub_settings.custom_data = item_names_str |
| 144 | hub_settings.save() |
| 145 | |
| 146 | @frappe.whitelist() |
| 147 | def update_category(hub_item_code, category): |
| 148 | connection = get_hub_connection() |
| 149 | |
| 150 | # args = frappe._dict(dict( |
| 151 | # doctype='Hub Category', |
| 152 | # hub_category_name=category |
| 153 | # )) |
| 154 | # response = connection.insert('Hub Category', args) |
| 155 | |
| 156 | response = connection.update('Hub Item', frappe._dict(dict( |
| 157 | doctype='Hub Item', |
| 158 | hub_category = category |
| 159 | )), hub_item_code) |
| 160 | |
| 161 | return response |
| 162 | |
| 163 | def make_opportunity(buyer_name, email_id): |
| 164 | buyer_name = "HUB-" + buyer_name |
| 165 | |
| 166 | if not frappe.db.exists('Lead', {'email_id': email_id}): |
| 167 | lead = frappe.new_doc("Lead") |
| 168 | lead.lead_name = buyer_name |
| 169 | lead.email_id = email_id |
| 170 | lead.save(ignore_permissions=True) |
| 171 | |
| 172 | o = frappe.new_doc("Opportunity") |
| 173 | o.enquiry_from = "Lead" |
| 174 | o.lead = frappe.get_all("Lead", filters={"email_id": email_id}, fields = ["name"])[0]["name"] |
| 175 | o.save(ignore_permissions=True) |
| 176 | |
| 177 | @frappe.whitelist() |
| 178 | def make_rfq_and_send_opportunity(item, supplier): |
| 179 | supplier = make_supplier(supplier) |
| 180 | contact = make_contact(supplier) |
| 181 | item = make_item(item) |
| 182 | rfq = make_rfq(item, supplier, contact) |
| 183 | status = send_opportunity(contact) |
| 184 | |
| 185 | return { |
| 186 | 'rfq': rfq, |
| 187 | 'hub_document_created': status |
| 188 | } |
| 189 | |
| 190 | def make_supplier(supplier): |
| 191 | # make supplier if not already exists |
| 192 | supplier = frappe._dict(json.loads(supplier)) |
| 193 | |
| 194 | if not frappe.db.exists('Supplier', {'supplier_name': supplier.supplier_name}): |
| 195 | supplier_doc = frappe.get_doc({ |
| 196 | 'doctype': 'Supplier', |
| 197 | 'supplier_name': supplier.supplier_name, |
| 198 | 'supplier_group': supplier.supplier_group, |
| 199 | 'supplier_email': supplier.supplier_email |
| 200 | }).insert() |
| 201 | else: |
| 202 | supplier_doc = frappe.get_doc('Supplier', supplier.supplier_name) |
| 203 | |
| 204 | return supplier_doc |
| 205 | |
| 206 | def make_contact(supplier): |
| 207 | contact_name = get_default_contact('Supplier', supplier.supplier_name) |
| 208 | # make contact if not already exists |
| 209 | if not contact_name: |
| 210 | contact = frappe.get_doc({ |
| 211 | 'doctype': 'Contact', |
| 212 | 'first_name': supplier.supplier_name, |
| 213 | 'email_id': supplier.supplier_email, |
| 214 | 'is_primary_contact': 1, |
| 215 | 'links': [ |
| 216 | {'link_doctype': 'Supplier', 'link_name': supplier.supplier_name} |
| 217 | ] |
| 218 | }).insert() |
| 219 | else: |
| 220 | contact = frappe.get_doc('Contact', contact_name) |
| 221 | |
| 222 | return contact |
| 223 | |
| 224 | def make_item(item): |
| 225 | # make item if not already exists |
| 226 | item = frappe._dict(json.loads(item)) |
| 227 | |
| 228 | if not frappe.db.exists('Item', {'item_code': item.item_code}): |
| 229 | item_doc = frappe.get_doc({ |
| 230 | 'doctype': 'Item', |
| 231 | 'item_code': item.item_code, |
| 232 | 'item_group': item.item_group, |
| 233 | 'is_item_from_hub': 1 |
| 234 | }).insert() |
| 235 | else: |
| 236 | item_doc = frappe.get_doc('Item', item.item_code) |
| 237 | |
| 238 | return item_doc |
| 239 | |
| 240 | def make_rfq(item, supplier, contact): |
| 241 | # make rfq |
| 242 | rfq = frappe.get_doc({ |
| 243 | 'doctype': 'Request for Quotation', |
| 244 | 'transaction_date': nowdate(), |
| 245 | 'status': 'Draft', |
| 246 | 'company': frappe.db.get_single_value('Hub Settings', 'company'), |
| 247 | 'message_for_supplier': 'Please supply the specified items at the best possible rates', |
| 248 | 'suppliers': [ |
| 249 | { 'supplier': supplier.name, 'contact': contact.name } |
| 250 | ], |
| 251 | 'items': [ |
| 252 | { |
| 253 | 'item_code': item.item_code, |
| 254 | 'qty': 1, |
| 255 | 'schedule_date': nowdate(), |
| 256 | 'warehouse': item.default_warehouse or get_root_of("Warehouse"), |
| 257 | 'description': item.description, |
| 258 | 'uom': item.stock_uom |
| 259 | } |
| 260 | ] |
| 261 | }).insert() |
| 262 | |
| 263 | rfq.save() |
| 264 | rfq.submit() |
| 265 | return rfq |
| 266 | |
| 267 | def send_opportunity(contact): |
| 268 | # Make Hub Message on Hub with lead data |
| 269 | doc = { |
| 270 | 'doctype': 'Lead', |
| 271 | 'lead_name': frappe.db.get_single_value('Hub Settings', 'company'), |
| 272 | 'email_id': frappe.db.get_single_value('Hub Settings', 'user') |
| 273 | } |
| 274 | |
| 275 | args = frappe._dict(dict( |
| 276 | doctype='Hub Message', |
| 277 | reference_doctype='Lead', |
| 278 | data=json.dumps(doc), |
| 279 | user=contact.email_id |
| 280 | )) |
| 281 | |
| 282 | connection = get_hub_connection() |
| 283 | response = connection.insert('Hub Message', args) |
| 284 | |
| 285 | return response.ok |