{"id":478018,"date":"2026-04-29T21:36:39","date_gmt":"2026-04-29T21:36:39","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=478018"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=478018","title":{"rendered":"FARA CRM. \u041a\u0430\u043a \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h3>CRM \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435: \u043a\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443 \u0441\u0435\u0431\u044f \u2014 \u0438 \u0447\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c<\/h3>\n<blockquote>\n<p>\u0421\u0442\u0430\u0442\u044c\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 Google Drive \u0438 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a \u043a CRM-\u0441\u0438\u0441\u0442\u0435\u043c\u0435 FARA \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043b, \u0432 \u043a\u0430\u043a\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043b\u0435\u0436\u0438\u0442 \u0444\u0430\u0439\u043b, \u0430 \u0432\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043c\u043e\u0433\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0447\u0435\u0440\u0435\u0437 CRM, \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u043b\u0430\u043a\u043e.<\/p>\n<\/blockquote>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a7a\/a9d\/371\/a7aa9d371f66b0a5085d7b9e69e94cb8.png\" alt=\"\u041a\u0430\u043d\u0431\u0430\u043d \u0444\u0430\u0439\u043b\u043e\u0432, \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437 CRM\" title=\"\u041a\u0430\u043d\u0431\u0430\u043d \u0444\u0430\u0439\u043b\u043e\u0432, \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437 CRM\" width=\"1919\" height=\"870\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a7a\/a9d\/371\/a7aa9d371f66b0a5085d7b9e69e94cb8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a7a\/a9d\/371\/a7aa9d371f66b0a5085d7b9e69e94cb8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041a\u0430\u043d\u0431\u0430\u043d \u0444\u0430\u0439\u043b\u043e\u0432, \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437 CRM<\/figcaption><\/div>\n<\/figure>\n<h3>\u0417\u0430\u0447\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438\u0437 CRM<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e \u2014 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e CRM \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0431\u044b\u0442\u044c \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u043c. \u0420\u0430\u043d\u044c\u0448\u0435 \u00ab\u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u043a \u0441\u0434\u0435\u043b\u043a\u0435\u00bb \u043e\u0437\u043d\u0430\u0447\u0430\u043b\u043e \u00ab\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u043e\u043f\u0438\u044e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 CRM, \u0430 \u0435\u0441\u043b\u0438 \u043a\u043e\u043c\u0443-\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u2014 \u0441\u043a\u0430\u0447\u0430\u0442\u044c, \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0437\u0430\u043d\u043e\u0432\u043e\u00bb. \u0421\u0435\u0439\u0447\u0430\u0441 \u043e\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \u0436\u0434\u0443\u0442 \u0434\u0440\u0443\u0433\u043e\u0433\u043e:<\/p>\n<ul>\n<li>\n<p>\u0435\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u044e\u0442 \u0432\u0434\u0432\u043e\u0451\u043c \u0441 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u043e\u043c \u043f\u0440\u044f\u043c\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0432\u043e\u043d\u043a\u0430 \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0437\u0430\u0445\u043e\u0434\u0438\u0442 \u0432 CRM \u2014 \u0443 \u043d\u0435\u0451 \u043e\u0442\u043a\u0440\u044b\u0442 Drive, \u0438 \u043e\u043d\u0430 \u0432\u0438\u0434\u0438\u0442 \u0432\u0441\u0435 \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u044b \u043f\u043e \u0441\u0434\u0435\u043b\u043a\u0430\u043c \u0432 \u043e\u0434\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043a\u0430\u043d \u0430\u043a\u0442\u0430 \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u0435\u0442 \u043d\u0430 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0434\u0438\u0441\u043a \u0447\u0435\u0440\u0435\u0437 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u2014 \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0430\u043c \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0435 \u0441\u0434\u0435\u043b\u043a\u0438, \u0431\u0435\u0437 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u00ab\u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u044c\u00bb.<\/p>\n<\/li>\n<\/ul>\n<p>\u00ab\u041d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u00bb \u2014 \u044d\u0442\u043e \u0441\u0430\u043c\u0430\u044f \u0441\u043a\u0443\u0447\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0438\u0437 \u0432\u0441\u0435\u0445, \u043e\u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f. \u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u0442\u043e, \u0447\u0442\u043e \u043e\u0431\u043b\u0430\u043a\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0441\u0440\u0435\u0434\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0430 CRM \u2014 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043e\u043a\u043e\u043d \u0432 \u044d\u0442\u0443 \u0441\u0440\u0435\u0434\u0443. \u041d\u0435 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c.<\/p>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u044d\u0442\u043e \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0432 FARA CRM \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043a\u043e\u0434\u0430 \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041c\u043e\u0434\u0443\u043b\u0438 <code>attachments_google<\/code> \u0438 <code>attachments_yandex<\/code> \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 \u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435, \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u0442\u0430\u043a, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u0441\u043a\u0430\u0436\u0435\u043c, OneDrive \u0438\u043b\u0438 Dropbox \u2014 \u044d\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u043f\u043e \u0442\u043e\u043c\u0443 \u0436\u0435 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0443.<\/p>\n<h3>\u0427\u0435\u0442\u044b\u0440\u0435 \u0438\u0434\u0435\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0432\u0438\u0433\u0430\u044e\u0442 \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435<\/h3>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u044b\u0440\u044f\u0442\u044c \u0432 \u043a\u043e\u0434, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0443, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c. \u042d\u0442\u043e \u0447\u0435\u0442\u044b\u0440\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u043d\u044c\u0448\u0435 \u0443\u043f\u0438\u0440\u0430\u043b\u0441\u044f \u0432 \u00ab\u043d\u0443, \u0443 \u043d\u0430\u0441 \u0444\u0430\u0439\u043b\u044b \u0432\u043d\u0443\u0442\u0440\u0438 CRM, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0438\u043a\u0430\u043a\u00bb.<\/p>\n<p><strong>1. \u0424\u0430\u0439\u043b \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u043d\u043b\u0430\u0439\u043d \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 \u043e\u0431\u043b\u0430\u043a\u0430.<\/strong> \u0414\u043e\u0433\u043e\u0432\u043e\u0440 \u043b\u0435\u0436\u0438\u0442 \u0432 Google Drive \u2014 \u0437\u043d\u0430\u0447\u0438\u0442, \u0435\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 Google Docs, \u043d\u0435 \u043d\u0430\u0448 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0449\u0438\u043a. \u041f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u0432 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a\u0435 \u2014 \u0435\u0451 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043e\u043d\u043b\u0430\u0439\u043d-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u042f\u043d\u0434\u0435\u043a\u0441\u0430. CRM \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0431\u044b\u0442\u044c Office. \u041e\u043d\u0430 \u043f\u0438\u0448\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u0438 \u0434\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043e\u0431\u043b\u0430\u043a\u0443 \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435.<\/p>\n<p><strong>2. \u0427\u0430\u0441\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0441 \u0434\u0438\u0441\u043a\u043e\u043c.<\/strong> \u0423 \u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0430, \u044e\u0440\u0438\u0441\u0442\u0430, \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0430 \u2014 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0431\u044b\u0442\u044c \u0443\u0447\u0451\u0442\u043a\u0438 \u0432 CRM. \u0418\u043c \u043e\u0442\u043a\u0440\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0430\u043f\u043a\u0435 <code>Sales\/<\/code> \u043d\u0430 Google Drive \u2014 \u0438 \u0432\u0441\u0451, \u043e\u043d\u0438 \u0432\u0438\u0434\u044f\u0442 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u043e \u0441\u0434\u0435\u043b\u043a\u0430\u043c. \u041d\u0438\u043a\u0442\u043e \u0438\u043c \u043d\u0435 \u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0435\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p><strong>3. \u041e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u0444\u0430\u0439\u043b, \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0439 \u0432 \u043e\u0431\u043b\u0430\u043a\u043e, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 CRM.<\/strong> \u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043a\u0438\u043d\u0443\u043b \u0441\u043a\u0430\u043d \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438 \u043f\u0440\u044f\u043c\u043e \u0441 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430. \u0427\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0443 \u043c\u0438\u043d\u0443\u0442 \u043e\u043d \u0443\u0432\u0438\u0434\u0438\u0442 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0435 \u0432 CRM, \u0431\u0435\u0437 \u0440\u0443\u0447\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u041f\u043e \u0442\u0430\u043a\u043e\u043c\u0443 \u0436\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f (\u0435\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044d\u0442\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435).<\/p>\n<p><strong>4. \u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u043a\u0430 \u043f\u043e \u0441\u0442\u0430\u0434\u0438\u044f\u043c.<\/strong> \u0423 \u0441\u0434\u0435\u043b\u043a\u0438 \u0435\u0441\u0442\u044c \u0441\u0442\u0430\u0434\u0438\u044f (\u043d\u043e\u0432\u0430\u044f \u2192 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u2192 \u043e\u043f\u043b\u0430\u0447\u0435\u043d\u0430 \u2192 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430). \u0424\u0430\u0439\u043b\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0436\u0438\u0442\u044c \u0432 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438. \u041f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u043b \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0432 kanban \u043d\u0430 \u00ab\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u0430\u00bb \u2014 \u0438 \u0432\u0441\u0435 \u0435\u0451 \u0444\u0430\u0439\u043b\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0435\u0445\u0430\u043b\u0438 \u0432 \u043f\u0430\u043f\u043a\u0443 <code>\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0435\/SO-0000123\/<\/code>. \u042d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u043c\u0430\u0433\u0438\u044f, \u0430 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u2014 \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u0438\u043c\u0451\u043d \u043f\u0430\u043f\u043e\u043a \u0438 \u043f\u0430\u0440\u0430 \u0445\u0443\u043a\u043e\u0432.<\/p>\n<p>\u0412\u043e\u043a\u0440\u0443\u0433 \u044d\u0442\u0438\u0445 \u0447\u0435\u0442\u044b\u0440\u0451\u0445 \u0438\u0434\u0435\u0439 \u0438 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0432\u0441\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/61c\/8d6\/725\/61c8d67256f4dab7c939f4cc41f506ce.png\" alt=\"\u0421\u0442\u0430\u0434\u0438\u0438 \u0441\u0434\u0435\u043b\u043e\u043a \u043d\u0430 kanban-\u0434\u043e\u0441\u043a\u0435. \u041f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.\" title=\"\u0421\u0442\u0430\u0434\u0438\u0438 \u0441\u0434\u0435\u043b\u043e\u043a \u043d\u0430 kanban-\u0434\u043e\u0441\u043a\u0435. \u041f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.\" width=\"1918\" height=\"867\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/61c\/8d6\/725\/61c8d67256f4dab7c939f4cc41f506ce.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/61c\/8d6\/725\/61c8d67256f4dab7c939f4cc41f506ce.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><em>\u0421\u0442\u0430\u0434\u0438\u0438 \u0441\u0434\u0435\u043b\u043e\u043a \u043d\u0430 kanban-\u0434\u043e\u0441\u043a\u0435. \u041f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.<\/em><\/figcaption><\/div>\n<\/figure>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e: Strategy + Route<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b CRM \u043d\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b\u0430\u0441\u044c \u0432 \u0441\u043f\u0430\u0433\u0435\u0442\u0442\u0438 \u0438\u0437 \u00ab\u0435\u0441\u043b\u0438 Google \u2014 \u0442\u043e \u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u2014 \u0442\u043e \u0438\u043d\u0430\u0447\u0435, \u0435\u0441\u043b\u0438 \u042f\u043d\u0434\u0435\u043a\u0441 \u2014 \u0442\u043e \u0435\u0449\u0451 \u043a\u0430\u043a-\u0442\u043e\u00bb, \u0443 \u043d\u0430\u0441 \u0434\u0432\u0430 \u0443\u0440\u043e\u0432\u043d\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438.<\/p>\n<p><strong>Strategy \u2014 \u044d\u0442\u043e \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b.<\/strong> \u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 CRUD \u043d\u0430\u0434 \u0444\u0430\u0439\u043b\u043e\u043c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435: \u0441\u043e\u0437\u0434\u0430\u0442\u044c, \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c, \u0443\u0434\u0430\u043b\u0438\u0442\u044c, \u043f\u043b\u044e\u0441 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443, \u043f\u043b\u044e\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c URL \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441\u0432\u043e\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f:<\/p>\n<pre><code class=\"python\">class StorageStrategyBase(ABC):    strategy_type: str = \"\"    @abstractmethod    async def create_file(self, storage, attachment, content, filename, ...): ...    @abstractmethod    async def read_file(self, storage, attachment) -&gt; bytes | None: ...    @abstractmethod    async def update_file(self, storage, attachment, content=None, ...): ...    @abstractmethod    async def delete_file(self, storage, attachment) -&gt; bool: ...    @abstractmethod    async def create_folder(self, storage, folder_name, parent_id=None, ...): ...    @abstractmethod    async def validate_connection(self, storage) -&gt; bool: ...    @abstractmethod    async def get_file_url(self, storage, attachment) -&gt; str | None: ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0439 \u0443\u0436\u0435 \u0442\u0440\u0438: <code>FileStoreStrategy<\/code> (\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0434\u0435\u0444\u043e\u043b\u0442), <code>GoogleDriveStrategy<\/code> \u0438 <code>YandexDiskStrategy<\/code>. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u2014 \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u043e\u0447\u043a\u0430 \u0432 <a href=\"http:\/\/app.py\"><code>app.py<\/code><\/a> \u043c\u043e\u0434\u0443\u043b\u044f:<\/p>\n<pre><code class=\"python\">register_strategy(GoogleDriveStrategy)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>Route \u2014 \u044d\u0442\u043e \u043a\u0443\u0434\u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b \u0438 \u043f\u043e\u0434 \u043a\u0430\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c.<\/strong> \u041c\u0430\u0440\u0448\u0440\u0443\u0442 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, \u043a\u0430\u043a \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f <code>create_file<\/code>, \u0435\u043c\u0443 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e. \u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f \u0441\u0434\u0435\u043b\u043a\u0438 <code>Sale#123<\/code> \u0444\u0430\u0439\u043b\u044b \u043f\u043e\u043f\u0430\u043b\u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 <code>Sales Orders\/SO-0000123-\u0418\u0432\u0430\u043d\u043e\u0432\/<\/code>, \u0430 \u043d\u0435 \u0432 \u043f\u043b\u043e\u0441\u043a\u0443\u044e \u043a\u0443\u0447\u0443. \u041f\u0440\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u0447\u0443\u0442\u044c \u043d\u0438\u0436\u0435.<\/p>\n<p>\u042d\u0442\u0438 \u0434\u0432\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0436\u0438\u0432\u0443\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u043f\u0438\u0448\u0443\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u043e\u0434 \u043e\u0431\u043b\u0430\u043a\u043e \u0438 \u0437\u0430\u0431\u044b\u0432\u0430\u044e\u0442. \u041c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0430\u0434\u043c\u0438\u043d \u043a\u043b\u0438\u043a\u0430\u043c\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/11d\/350\/330\/11d35033053701ee49325a96f42d5ba8.png\" alt=\"\u0421\u0432\u044f\u0437\u043a\u0430 Strategy + Route: \u0447\u0442\u043e \u043a\u0443\u0434\u0430 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0438 \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c.\" title=\"\u0421\u0432\u044f\u0437\u043a\u0430 Strategy + Route: \u0447\u0442\u043e \u043a\u0443\u0434\u0430 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0438 \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c.\" width=\"1918\" height=\"862\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/11d\/350\/330\/11d35033053701ee49325a96f42d5ba8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/11d\/350\/330\/11d35033053701ee49325a96f42d5ba8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><em>\u0421\u0432\u044f\u0437\u043a\u0430 Strategy + Route: \u0447\u0442\u043e \u043a\u0443\u0434\u0430 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0438 \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c.<\/em><\/figcaption><\/div>\n<\/figure>\n<hr\/>\n<h3>\u041c\u043e\u0434\u0443\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449: \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 Google \u0438 \u042f\u043d\u0434\u0435\u043a\u0441\u0430<\/h3>\n<p>\u0421\u043d\u0430\u0440\u0443\u0436\u0438 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0443\u043d\u043a\u0442 \u0432 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c \u00ab\u0422\u0438\u043f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u00bb: FileStore, Google Drive, Yandex Disk. \u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 <code>attachments_google<\/code> \u0438 <code>attachments_yandex<\/code>.<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0451\u0445 \u0447\u0430\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><strong>Mixin<\/strong> \u2014 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u044c <code>AttachmentStorage<\/code>, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u0441\u0432\u043e\u0438 \u043f\u043e\u043b\u044f (<code>google_credentials<\/code>, <code>google_team_id<\/code>, <code>yandex_access_token<\/code>, <code>yandex_refresh_token<\/code> \u0438 \u0442. \u0434.). \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440 <code>@extend<\/code>, \u0431\u0435\u0437 \u043f\u0440\u0430\u0432\u043e\u043a \u044f\u0434\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>Strategy<\/strong> \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0432\u044b\u0448\u0435 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e API.<\/p>\n<\/li>\n<li>\n<p><strong>OAuth-\u0440\u043e\u0443\u0442\u0435\u0440<\/strong> \u2014 \u0434\u0432\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430: <code>\/{provider}\/auth\/{storage_id}<\/code> (\u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>authorization_url<\/code>) \u0438 <code>\/{provider}\/callback<\/code> (\u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u043d\u0430 \u0442\u043e\u043a\u0435\u043d\u044b, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0432 storage).<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u044d\u0442\u043e \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u043e \u0438 \u0437\u0435\u0440\u043a\u0430\u043b\u044c\u043d\u043e \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 access-\u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u042f\u043d\u0434\u0435\u043a\u0441\u0435:<\/p>\n<pre><code class=\"python\">async def _refresh_access_token(self, storage):    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:        response = await client.post(OAUTH_TOKEN_URL, data={            \"grant_type\": \"refresh_token\",            \"refresh_token\": storage.yandex_refresh_token,            \"client_id\": storage.yandex_client_id,            \"client_secret\": storage.yandex_client_secret,        })    # ...\u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0432 storage<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 Google \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u0438\u0431\u0435 <code>google-auth<\/code>, \u043d\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0442\u043e\u0442 \u0436\u0435: \u043f\u0440\u0438 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d \u043c\u043e\u043b\u0447\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u0432 \u0411\u0414 \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u0441\u0432\u0435\u0436\u0438\u0435 credentials, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u0435\u0442.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f62\/9e7\/6a1\/f629e76a1c7a8f8fff8bd4f732e52229.png\" alt=\" \u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 Google Drive \u0432 FARA CRM.\" title=\" \u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 Google Drive \u0432 FARA CRM.\" width=\"1919\" height=\"866\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f62\/9e7\/6a1\/f629e76a1c7a8f8fff8bd4f732e52229.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f62\/9e7\/6a1\/f629e76a1c7a8f8fff8bd4f732e52229.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><em> \u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 Google Drive \u0432 FARA CRM.<\/em><\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5dd\/796\/bd8\/5dd796bd804f7b9532e99a48db15453b.png\" alt=\"\u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a.\" title=\"\u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a.\" width=\"1918\" height=\"870\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/5dd\/796\/bd8\/5dd796bd804f7b9532e99a48db15453b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5dd\/796\/bd8\/5dd796bd804f7b9532e99a48db15453b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><em>\u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a.<\/em><\/figcaption><\/div>\n<\/figure>\n<p>\u0427\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c FARA, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438, <strong>\u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0432\u0438\u0434\u0438\u0442, \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0444\u0430\u0439\u043b<\/strong>. \u041f\u0440\u0435\u0432\u044c\u044e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0444\u0430\u0439\u043b \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0441\u0441\u044b\u043b\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u2014 \u0430 \u0432\u043d\u0443\u0442\u0440\u0438 CRM, \u043f\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u0438\u043b\u0438 \u0438\u0437 \u043e\u0431\u043b\u0430\u043a\u0430, \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u043d\u0430\u043c \u0431\u044b\u043b \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u0435\u043d: \u043e\u0431\u043b\u0430\u043a\u043e \u2014 \u044d\u0442\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u0430 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u00ab\u0432\u0442\u043e\u0440\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u0439\u00bb.<\/p>\n<hr\/>\n<h3>\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u2014 \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0444\u0438\u0447\u0430, \u0440\u0430\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u043e\u0438\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435<\/h3>\n<p>\u041c\u0430\u0440\u0448\u0440\u0443\u0442 (<code>AttachmentRoute<\/code>) \u2014 \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0434\u0432\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 CRM: <strong>\u043a\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043a\u043e\u0440\u043d\u0435\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443<\/strong> \u044d\u0442\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435 \u0438 <strong>\u043a\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438<\/strong> \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0451.<\/p>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e:<\/p>\n<pre><code class=\"python\">class AttachmentRoute(DotModel):    name: str           # \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f    model: str | None   # 'sale', 'lead', None \u0434\u043b\u044f fallback-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430    priority: int       # \u0432\u044b\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u2014 \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442    pattern_root: str   # \u0448\u0430\u0431\u043b\u043e\u043d \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 \u043c\u043e\u0434\u0435\u043b\u0438    pattern_record: str # \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0430\u043f\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0438    flat: bool          # \u0431\u0435\u0437 \u043f\u043e\u0434\u043f\u0430\u043f\u043e\u043a \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c?    filter: list | None # \u0444\u0438\u043b\u044c\u0442\u0440 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (DSL CRM)    storage_id: M2O     # \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f    active: bool<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 <code>pattern_root<\/code> \u0438 <code>pattern_record<\/code> \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435: \u0438\u043c\u044f \u043c\u043e\u0434\u0435\u043b\u0438, ID, \u043b\u044e\u0431\u044b\u0435 \u043f\u043e\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438, \u043f\u043b\u044e\u0441 \u0445\u0435\u043b\u043f\u0435\u0440 <code>zfill<\/code> (\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0443\u043b\u044f\u043c\u0438 \u0434\u043e \u0441\u0435\u043c\u0438 \u0437\u043d\u0430\u043a\u043e\u0432). \u041f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code>pattern_root   = \"Sales Orders\"pattern_record = \"SO-{zfill(id)}-{name}\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<pre><code>Drive\/\u2514\u2500\u2500 Sales Orders\/    \u251c\u2500\u2500 SO-0000123-\u0418\u0432\u0430\u043d\u043e\u0432\/    \u2502   \u251c\u2500\u2500 contract.pdf    \u2502   \u2514\u2500\u2500 invoice.pdf    \u2514\u2500\u2500 SO-0000124-\u041f\u0435\u0442\u0440\u043e\u0432\/        \u2514\u2500\u2500 proposal.docx<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0443\u0436\u0435 \u043f\u0430\u043f\u043a\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0443 \u2014 \u0438 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0434\u043b\u044f \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430, \u043d\u0435 \u0437\u043d\u0430\u044e\u0449\u0435\u0433\u043e CRM. \u041d\u0435 <code>attachments_42_storage_3_file_uuid.bin<\/code>, \u0430 <code>SO-0000123-\u0418\u0432\u0430\u043d\u043e\u0432\/contract.pdf<\/code>.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/57e\/ffb\/ac8\/57effbac8dd9ff9251ff2dbb52088463.png\" alt=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430: \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u043a\u0430\u043a \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.\" title=\"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430: \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u043a\u0430\u043a \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.\" width=\"1919\" height=\"871\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/57e\/ffb\/ac8\/57effbac8dd9ff9251ff2dbb52088463.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/57e\/ffb\/ac8\/57effbac8dd9ff9251ff2dbb52088463.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><em>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430: \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u043a\u0430\u043a \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.<\/em><\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a02\/b04\/401\/a02b04401239bb172970f2240ad1ddd0.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u0432 Google Drive, \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443.\" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u0432 Google Drive, \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443.\" width=\"1916\" height=\"869\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a02\/b04\/401\/a02b04401239bb172970f2240ad1ddd0.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a02\/b04\/401\/a02b04401239bb172970f2240ad1ddd0.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><em>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u0432 Google Drive, \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443.<\/em><\/figcaption><\/div>\n<\/figure>\n<h4>\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b, \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 fallback<\/h4>\n<p>\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u043d\u0430 \u043e\u0434\u043d\u0443 \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>\u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u00abVIP-\u043a\u043b\u0438\u0435\u043d\u0442\u044b\u00bb \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c <code>[(\"client_tier\", \"=\", \"vip\")]<\/code>, \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 100, \u043f\u0430\u0442\u0442\u0435\u0440\u043d <code>VIP\/{name}<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c <code>sale<\/code>, \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 10;<\/p>\n<\/li>\n<li>\n<p>fallback-\u043c\u0430\u0440\u0448\u0440\u0443\u0442 (<code>model = None<\/code>) \u2014 \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e, \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u043f\u0430\u043b\u043e \u043d\u0438 \u0432 \u043e\u0434\u0438\u043d \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430:<\/p>\n<pre><code class=\"python\">@classmethodasync def get_route_for_attachment(cls, res_model, res_id):    if res_model and res_id:        # 1) \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043f\u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u2014 \u043f\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443        specific = await cls.search(filter=[            (\"active\", \"=\", True),            (\"model\", \"=\", res_model),        ], sort=\"priority\", order=\"DESC\")        for route in specific:            if await route._check_record_in_filter(res_id):                return route    # 2) fallback (model=None) \u2014 \u043f\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443    fallback = await cls.search(filter=[        (\"active\", \"=\", True),        (\"model\", \"=\", None),    ], sort=\"priority\", order=\"DESC\")    return fallback[0] if fallback else None<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u00ab\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u00bb \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u0431\u0435\u0436\u0434\u0430\u0435\u0442 fallback \u2014 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0443 fallback \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0432\u044b\u0448\u0435. \u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u043e\u0434\u0438\u043d \u0430\u0434\u043c\u0438\u043d \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0449\u0438\u0439 fallback \u043d\u0430 \u0432\u0441\u044e CRM, \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b, \u0438 \u043e\u043d\u0438 \u043d\u0435 \u0434\u0435\u0440\u0443\u0442\u0441\u044f.<\/p>\n<hr\/>\n<h3>\u0422\u0440\u0438 \u0442\u0438\u043f\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0444\u043b\u0430\u0433\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e CRM \u0438 \u043e\u0431\u043b\u0430\u043a\u043e \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u0430\u043c\u0438:<\/p>\n<pre><code class=\"python\">enable_realtime      = Boolean(default=False, ...)  # \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438enable_one_way_cron  = Boolean(default=False, ...)  # CRM \u2192 \u043e\u0431\u043b\u0430\u043a\u043e, \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044eenable_two_way_cron  = Boolean(default=False, ...)  # CRM \u2194 \u043e\u0431\u043b\u0430\u043a\u043e, \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u2014 \u043a\u0430\u043a \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"python\">file_missing_cloud   # \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0435\u0441\u0442\u044c \u0432 CRM, \u043d\u043e \u043d\u0435\u0442 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435file_missing_local   # \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0435\u0441\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435, \u043d\u043e \u043d\u0435\u0442 \u0432 CRM<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>Realtime (\u043e\u043d\u043b\u0430\u0439\u043d).<\/strong> \u0424\u0430\u0439\u043b \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438 \u2192 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u043e\u0431\u043b\u0430\u043a\u043e. \u042d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u043b\u0430\u043a\u043e \u2014 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0430 CRM \u2014 \u043a\u043b\u0438\u0435\u043d\u0442.<\/p>\n<p><strong>One-way cron.<\/strong> \u041f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0430\u0437 \u0432 \u0447\u0430\u0441) \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0430-\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0442\u043e\u0440: \u0432\u0441\u0451, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438 \u0435\u0449\u0451 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435, \u0434\u043e\u0435\u0437\u0436\u0430\u0435\u0442 \u0434\u043e \u043d\u0435\u0433\u043e \u0431\u0430\u0442\u0447\u0435\u043c. \u041f\u043e\u043b\u0435\u0437\u043d\u043e, \u0435\u0441\u043b\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 \u043e\u0431\u043b\u0430\u043a\u043e \u043d\u0435\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e\u0431\u044b UI \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0430\u043b \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445.<\/p>\n<p><strong>Two-way cron \u2014 \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f.<\/strong> \u0422\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u00ab\u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043a\u0438\u043d\u0443\u043b \u0441\u043a\u0430\u043d \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438 \u043f\u0440\u044f\u043c\u043e \u0441 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430\u00bb. Cron \u043e\u0431\u0445\u043e\u0434\u0438\u0442 \u043f\u0430\u043f\u043a\u0438 \u043e\u0431\u043b\u0430\u043a\u0430, \u043f\u043e <code>custom_properties<\/code> (<code>route_id<\/code>, <code>res_model<\/code>, <code>res_id<\/code>) \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442, \u043a \u043a\u0430\u043a\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b, \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 <code>Attachment<\/code> \u0432 CRM \u0441 \u043f\u0443\u0441\u0442\u044b\u043c <code>content<\/code>, \u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c <code>storage_file_id<\/code>. \u0414\u0430\u043b\u044c\u0448\u0435 \u044d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u2014 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043b\u044e\u0431\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435.<\/p>\n<hr\/>\n<h3>Google Shared Drive (Team)<\/h3>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0430\u044f \u0444\u0438\u0447\u0430 \u2014 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Shared Drive \u0432 Google. \u042d\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u0435 \u0434\u0438\u0441\u043a\u0438, \u0433\u0434\u0435 \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0435\u043c \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a, \u0430 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f. \u0415\u0441\u043b\u0438 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u0443\u0432\u043e\u043b\u044c\u043d\u044f\u0435\u0442\u0441\u044f \u2014 \u0435\u0433\u043e \u043b\u0438\u0447\u043d\u044b\u0439 Drive \u0443\u0445\u043e\u0434\u0438\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0438\u043c, \u0438 \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u043f\u043e \u0441\u0434\u0435\u043b\u043a\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c. \u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b\u044b \u043b\u0435\u0436\u0430\u0442 \u043d\u0430 Shared Drive, \u043d\u0438\u0447\u0435\u0433\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u043d\u0435 \u0441\u043b\u0443\u0447\u0438\u0442\u0441\u044f.<\/p>\n<p>\u0412 \u043c\u043e\u0434\u0443\u043b\u0435 <code>attachments_google<\/code> \u044d\u0442\u043e \u0434\u0432\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u044f:<\/p>\n<pre><code class=\"python\">google_team_enabled: bool = Boolean(default=False, string=\"Use Shared Drive\")google_team_id:      str  = Char(string=\"Shared Drive ID\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0432 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u2014 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 <code>supportsAllDrives=True<\/code> \/ <code>supportsTeamDrives=True<\/code> \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 Drive API. \u0421\u043d\u0430\u0440\u0443\u0436\u0438 \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u0447\u0435\u043a\u0431\u043e\u043a\u0441 \u0432 \u0444\u043e\u0440\u043c\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430.<\/p>\n<p>\u0414\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434 \u044d\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e: \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043a \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0434\u0438\u0441\u043a\u0430\u043c, \u0430 \u043d\u0435 \u043a \u043b\u0438\u0447\u043d\u044b\u043c. \u041c\u043d\u043e\u0433\u0438\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0443\u043c\u0435\u044e\u0442 \u2014 \u0430 \u0443 \u043d\u0430\u0441 \u044d\u0442\u043e \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u0447\u043a\u0438 \u0432 \u0444\u043e\u0440\u043c\u0435.<\/p>\n<hr\/>\n<h3>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c OAuth: \u0447\u0442\u043e \u043c\u044b \u0445\u0440\u0430\u043d\u0438\u043c \u0438 \u043a\u0430\u043a<\/h3>\n<p>\u0422\u0435\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u043b\u044e\u0431\u044f\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u044f\u0445, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u00ab\u0438 \u0442\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u00bb. \u041f\u043e\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0443 \u043d\u0430\u0441.<\/p>\n<p><strong>\u041b\u043e\u0433\u0438\u043d\u044b \u0438 \u043f\u0430\u0440\u043e\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0431\u043b\u0430\u043a\u0430 \u043c\u044b \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u043c.<\/strong> \u0422\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u043a\u0435\u043d\u044b OAuth2, \u0432\u044b\u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u043c \u0441 \u044f\u0432\u043d\u043e\u0433\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 scope-\u044b.<\/p>\n<p>\u0414\u043b\u044f <strong>Google<\/strong>:<\/p>\n<ul>\n<li>\n<p><code>google_json_credentials<\/code> \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <code>credentials.json<\/code> (client_id \/ client_secret \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f), \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0430\u0434\u043c\u0438\u043d\u043e\u043c \u043e\u0434\u0438\u043d \u0440\u0430\u0437. \u042d\u0442\u043e credentials \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u043d\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p><code>google_credentials<\/code> \u2014 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 OAuth2 credentials \u0441 access\/refresh \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438. \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0438 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><code>google_refresh_token<\/code> \u2014 \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c access-\u0442\u043e\u043a\u0435\u043d \u043c\u043e\u043b\u0447\u0430, \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>Scope-\u044b: <code>drive<\/code> \u0438 <code>drive.file<\/code>. \u041d\u0438\u0447\u0435\u0433\u043e \u043b\u0438\u0448\u043d\u0435\u0433\u043e.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f <strong>\u042f\u043d\u0434\u0435\u043a\u0441\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p><code>yandex_client_id<\/code> \/ <code>yandex_client_secret<\/code> \u2014 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e OAuth-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><code>yandex_access_token<\/code> \/ <code>yandex_refresh_token<\/code> \/ <code>yandex_token_expires_at<\/code>.<\/p>\n<\/li>\n<li>\n<p>Scope-\u044b: <code>cloud_api:<\/code><a href=\"http:\/\/disk.read\"><code>disk.read<\/code><\/a> \u0438 <code>cloud_api:disk.write<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>OAuth-\u0444\u043b\u043e\u0443 \u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 authorization code: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0436\u043c\u0451\u0442 \u00ab\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u00bb \u0432 \u0444\u043e\u0440\u043c\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u0435\u043c\u0443 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430, \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u044f \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0442 \u043d\u0430 \u043d\u0430\u0448 endpoint <code>\/{provider}\/callback?code=...&amp;state=...<\/code>. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>state<\/code> \u043c\u044b \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 storage (<code>*_verify_code<\/code>) \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0435 \u2014 \u044d\u0442\u043e \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 CSRF \u043d\u0430 \u043a\u043e\u043b\u0431\u044d\u043a\u0435. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <code>state<\/code> \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u043c\u0435\u043d\u0430.<\/p>\n<p>\u041e\u0434\u0438\u043d \u0432\u0430\u0436\u043d\u044b\u0439 \u043d\u044e\u0430\u043d\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0435\u043d\u0435\u0431\u0440\u0435\u0447\u044c: <strong>\u043f\u0440\u0438 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0438 \u0444\u0430\u0439\u043b\u0430 \u042f\u043d\u0434\u0435\u043a\u0441 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 302 \u043d\u0430 CDN<\/strong>, \u0438 <code>httpx<\/code> \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u044b \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u044f\u0432\u043d\u043e \u0441\u0442\u0430\u0432\u0438\u043c <code>follow_redirects=True<\/code> \u2014 \u043d\u043e <strong>\u0442\u043e\u043b\u044c\u043a\u043e<\/strong> \u0434\u043b\u044f \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 upload\/download URL, <strong>\u043d\u0435 \u0434\u043b\u044f<\/strong> API-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 <code>Authorization: OAuth \u2026<\/code>. \u0418\u043d\u0430\u0447\u0435 \u043f\u0440\u0438 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u044d\u043a\u0437\u043e\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0435 \u0442\u043e\u043a\u0435\u043d \u043c\u043e\u0436\u0435\u0442 \u0443\u0435\u0445\u0430\u0442\u044c \u043d\u0430 \u0447\u0443\u0436\u043e\u0439 \u0445\u043e\u0441\u0442.<\/p>\n<pre><code class=\"python\"># OK \u2014 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0439 download URL, \u043c\u043e\u0436\u043d\u043e \u0438\u0434\u0442\u0438 \u0437\u0430 \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u043casync with httpx.AsyncClient(timeout=HTTP_TIMEOUT, follow_redirects=True) as c:    file_resp = await c.get(href)# \u041d\u0415 OK \u2014 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441 OAuth-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c, follow_redirects \u043d\u0435 \u043d\u0443\u0436\u0435\u043dasync with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as c:    response = await c.request(method, url, headers={\"Authorization\": f\"OAuth {token}\"}, ...)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0442\u0430 \u0441\u0430\u043c\u0430\u044f \u0433\u0440\u0430\u043d\u0438\u0446\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f \u0433\u0440\u043e\u043c\u043a\u0438\u0435 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0441 \u0443\u0442\u0435\u0447\u043a\u043e\u0439 \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0432 \u043b\u043e\u0433\u0438 \u0438\u043b\u0438 \u043f\u0440\u043e\u043a\u0441\u0438.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8e0\/f50\/665\/8e0f506652e529917686ea6250e4a237.png\" alt=\" \u041e\u043a\u043d\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u2014 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f.\" title=\" \u041e\u043a\u043d\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u2014 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f.\" width=\"1913\" height=\"797\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/8e0\/f50\/665\/8e0f506652e529917686ea6250e4a237.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8e0\/f50\/665\/8e0f506652e529917686ea6250e4a237.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><em> \u041e\u043a\u043d\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u2014 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f.<\/em><\/figcaption><\/div>\n<\/figure>\n<hr\/>\n<h3>\u0427\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432 \u0438\u0442\u043e\u0433\u0435<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432 \u043e\u0434\u043d\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435: <strong>CRM \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0431\u044b\u0442\u044c \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c \u043a \u0444\u0430\u0439\u043b\u0430\u043c \u2014 \u0438 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0438\u0433\u0440\u0430\u043b\u0438 \u0432\u0441\u0435<\/strong>.<\/p>\n<p>\u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e, \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0444\u0430\u0439\u043b: \u043e\u043d \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438, \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u0440\u0435\u0432\u044c\u044e \u0438\u043b\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440. \u0411\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u0443\u0447\u0451\u0442\u043a\u0430 \u0432 CRM \u2014 \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043f\u0430\u043f\u043a\u0430 <code>Sales Orders<\/code> \u043d\u0430 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u043c Google Drive, \u0438 \u043e\u043d \u0442\u0430\u043c \u043f\u043e\u043b\u043d\u043e\u043f\u0440\u0430\u0432\u043d\u044b\u0439 \u0436\u0438\u0442\u0435\u043b\u044c. \u0410\u0434\u043c\u0438\u043d \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u043a\u0443 \u043f\u043e\u0434 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043a\u043b\u0438\u043a\u0430\u043c\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u0430 \u043d\u0435 \u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u043a\u043e\u0434\u0430. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u043e\u0431\u043b\u0430\u043a\u043e \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0435\u0439.<\/p>\n<p>\u041c\u043e\u0434\u0443\u043b\u0438 <code>attachments_google<\/code> \u0438 <code>attachments_yandex<\/code> \u0432 FARA CRM \u2014 <strong>\u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435<\/strong>, \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435, \u0438 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0441\u0438\u043c\u043c\u0435\u0442\u0440\u0438\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043b\u0435\u0433\u043a\u043e \u0431\u044b\u043b\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0440\u044f\u0434\u043e\u043c \u0438 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u044b (\u0430 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043e\u043d\u0438 \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u043a\u0430\u0436\u0435\u0442\u0441\u044f).<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c CRM, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0444\u0430\u0439\u043b\u044b \u2014 \u044d\u0442\u043e \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u00ab\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0441\u043a\u0430\u0447\u0430\u043b, \u043f\u0435\u0440\u0435\u0441\u043b\u0430\u043b\u00bb \u2014 \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u044d\u0442\u043e\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442, \u043a\u043e\u0433\u0434\u0430 CRM \u0438 \u043e\u0431\u043b\u0430\u043a\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435.<\/p>\n<p><strong>P. S.<\/strong> \u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u043c\u043e\u0434\u0443\u043b\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u2014 \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043b\u043e\u0436\u0438\u043c \u0440\u0430\u0437\u0431\u043e\u0440 <code>attachments_yandex<\/code> \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0451\u0439: \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u043d OAuth, \u043a\u0430\u043a \u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043a\u0432\u043e\u0442\u044b \u042f\u043d\u0434\u0435\u043a\u0441\u0430. \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0442\u0435\u0441\u044c.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1029850\/\">https:\/\/habr.com\/ru\/articles\/1029850\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>CRM \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435: \u043a\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443 \u0441\u0435\u0431\u044f \u2014 \u0438 \u0447\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c\u0421\u0442\u0430\u0442\u044c\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 Google Drive \u0438 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a \u043a CRM-\u0441\u0438\u0441\u0442\u0435\u043c\u0435 FARA \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043b, \u0432 \u043a\u0430\u043a\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043b\u0435\u0436\u0438\u0442 \u0444\u0430\u0439\u043b, \u0430 \u0432\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043c\u043e\u0433\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0447\u0435\u0440\u0435\u0437 CRM, \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u043b\u0430\u043a\u043e.\u041a\u0430\u043d\u0431\u0430\u043d \u0444\u0430\u0439\u043b\u043e\u0432, \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437 CRM\u0417\u0430\u0447\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438\u0437 CRM\u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e \u2014 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e CRM \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0431\u044b\u0442\u044c \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u043c. \u0420\u0430\u043d\u044c\u0448\u0435 \u00ab\u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u0444\u0430\u0439\u043b \u043a \u0441\u0434\u0435\u043b\u043a\u0435\u00bb \u043e\u0437\u043d\u0430\u0447\u0430\u043b\u043e \u00ab\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u043e\u043f\u0438\u044e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 CRM, \u0430 \u0435\u0441\u043b\u0438 \u043a\u043e\u043c\u0443-\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u2014 \u0441\u043a\u0430\u0447\u0430\u0442\u044c, \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0437\u0430\u043d\u043e\u0432\u043e\u00bb. \u0421\u0435\u0439\u0447\u0430\u0441 \u043e\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \u0436\u0434\u0443\u0442 \u0434\u0440\u0443\u0433\u043e\u0433\u043e:\u0435\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u044e\u0442 \u0432\u0434\u0432\u043e\u0451\u043c \u0441 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u043e\u043c \u043f\u0440\u044f\u043c\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0432\u043e\u043d\u043a\u0430 \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c;\u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0437\u0430\u0445\u043e\u0434\u0438\u0442 \u0432 CRM \u2014 \u0443 \u043d\u0435\u0451 \u043e\u0442\u043a\u0440\u044b\u0442 Drive, \u0438 \u043e\u043d\u0430 \u0432\u0438\u0434\u0438\u0442 \u0432\u0441\u0435 \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u044b \u043f\u043e \u0441\u0434\u0435\u043b\u043a\u0430\u043c \u0432 \u043e\u0434\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435;\u0441\u043a\u0430\u043d \u0430\u043a\u0442\u0430 \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u0435\u0442 \u043d\u0430 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0434\u0438\u0441\u043a \u0447\u0435\u0440\u0435\u0437 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u2014 \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0430\u043c \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0435 \u0441\u0434\u0435\u043b\u043a\u0438, \u0431\u0435\u0437 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u00ab\u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u044c\u00bb.\u00ab\u041d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u00bb \u2014 \u044d\u0442\u043e \u0441\u0430\u043c\u0430\u044f \u0441\u043a\u0443\u0447\u043d\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0438\u0437 \u0432\u0441\u0435\u0445, \u043e\u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f. \u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u0442\u043e, \u0447\u0442\u043e \u043e\u0431\u043b\u0430\u043a\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0441\u0440\u0435\u0434\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u0430 CRM \u2014 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043e\u043a\u043e\u043d \u0432 \u044d\u0442\u0443 \u0441\u0440\u0435\u0434\u0443. \u041d\u0435 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c.\u0414\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u044d\u0442\u043e \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0432 FARA CRM \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043a\u043e\u0434\u0430 \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041c\u043e\u0434\u0443\u043b\u0438 attachments_google \u0438 attachments_yandex \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 \u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435, \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u0442\u0430\u043a, \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u0441\u043a\u0430\u0436\u0435\u043c, OneDrive \u0438\u043b\u0438 Dropbox \u2014 \u044d\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u043f\u043e \u0442\u043e\u043c\u0443 \u0436\u0435 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0443.\u0427\u0435\u0442\u044b\u0440\u0435 \u0438\u0434\u0435\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0432\u0438\u0433\u0430\u044e\u0442 \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043d\u044b\u0440\u044f\u0442\u044c \u0432 \u043a\u043e\u0434, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0443, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c. \u042d\u0442\u043e \u0447\u0435\u0442\u044b\u0440\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u043d\u044c\u0448\u0435 \u0443\u043f\u0438\u0440\u0430\u043b\u0441\u044f \u0432 \u00ab\u043d\u0443, \u0443 \u043d\u0430\u0441 \u0444\u0430\u0439\u043b\u044b \u0432\u043d\u0443\u0442\u0440\u0438 CRM, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0438\u043a\u0430\u043a\u00bb.1. \u0424\u0430\u0439\u043b \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u043d\u043b\u0430\u0439\u043d \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 \u043e\u0431\u043b\u0430\u043a\u0430. \u0414\u043e\u0433\u043e\u0432\u043e\u0440 \u043b\u0435\u0436\u0438\u0442 \u0432 Google Drive \u2014 \u0437\u043d\u0430\u0447\u0438\u0442, \u0435\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 Google Docs, \u043d\u0435 \u043d\u0430\u0448 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0449\u0438\u043a. \u041f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043b\u0435\u0436\u0438\u0442 \u0432 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a\u0435 \u2014 \u0435\u0451 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043e\u043d\u043b\u0430\u0439\u043d-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u042f\u043d\u0434\u0435\u043a\u0441\u0430. CRM \u043d\u0435 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0431\u044b\u0442\u044c Office. \u041e\u043d\u0430 \u043f\u0438\u0448\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u0438 \u0434\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043e\u0431\u043b\u0430\u043a\u0443 \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435.2. \u0427\u0430\u0441\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0441 \u0434\u0438\u0441\u043a\u043e\u043c. \u0423 \u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0430, \u044e\u0440\u0438\u0441\u0442\u0430, \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0430 \u2014 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0431\u044b\u0442\u044c \u0443\u0447\u0451\u0442\u043a\u0438 \u0432 CRM. \u0418\u043c \u043e\u0442\u043a\u0440\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0430\u043f\u043a\u0435 Sales\/ \u043d\u0430 Google Drive \u2014 \u0438 \u0432\u0441\u0451, \u043e\u043d\u0438 \u0432\u0438\u0434\u044f\u0442 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u043e \u0441\u0434\u0435\u043b\u043a\u0430\u043c. \u041d\u0438\u043a\u0442\u043e \u0438\u043c \u043d\u0435 \u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0435\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b.3. \u041e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u0444\u0430\u0439\u043b, \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0439 \u0432 \u043e\u0431\u043b\u0430\u043a\u043e, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 CRM. \u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u043a\u0438\u043d\u0443\u043b \u0441\u043a\u0430\u043d \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438 \u043f\u0440\u044f\u043c\u043e \u0441 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430. \u0427\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0443 \u043c\u0438\u043d\u0443\u0442 \u043e\u043d \u0443\u0432\u0438\u0434\u0438\u0442 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0435 \u0432 CRM, \u0431\u0435\u0437 \u0440\u0443\u0447\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u041f\u043e \u0442\u0430\u043a\u043e\u043c\u0443 \u0436\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f (\u0435\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044d\u0442\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435).4. \u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u043a\u0430 \u043f\u043e \u0441\u0442\u0430\u0434\u0438\u044f\u043c. \u0423 \u0441\u0434\u0435\u043b\u043a\u0438 \u0435\u0441\u0442\u044c \u0441\u0442\u0430\u0434\u0438\u044f (\u043d\u043e\u0432\u0430\u044f \u2192 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u2192 \u043e\u043f\u043b\u0430\u0447\u0435\u043d\u0430 \u2192 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430). \u0424\u0430\u0439\u043b\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0436\u0438\u0442\u044c \u0432 \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438. \u041f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u043b \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0432 kanban \u043d\u0430 \u00ab\u041e\u043f\u043b\u0430\u0447\u0435\u043d\u0430\u00bb \u2014 \u0438 \u0432\u0441\u0435 \u0435\u0451 \u0444\u0430\u0439\u043b\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0435\u0445\u0430\u043b\u0438 \u0432 \u043f\u0430\u043f\u043a\u0443 \u041e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0435\/SO-0000123\/. \u042d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u0430\u043a \u043c\u0430\u0433\u0438\u044f, \u0430 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u2014 \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u0438\u043c\u0451\u043d \u043f\u0430\u043f\u043e\u043a \u0438 \u043f\u0430\u0440\u0430 \u0445\u0443\u043a\u043e\u0432.\u0412\u043e\u043a\u0440\u0443\u0433 \u044d\u0442\u0438\u0445 \u0447\u0435\u0442\u044b\u0440\u0451\u0445 \u0438\u0434\u0435\u0439 \u0438 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f \u0432\u0441\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f.\u0421\u0442\u0430\u0434\u0438\u0438 \u0441\u0434\u0435\u043b\u043e\u043a \u043d\u0430 kanban-\u0434\u043e\u0441\u043a\u0435. \u041f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e: Strategy + Route\u0427\u0442\u043e\u0431\u044b CRM \u043d\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b\u0430\u0441\u044c \u0432 \u0441\u043f\u0430\u0433\u0435\u0442\u0442\u0438 \u0438\u0437 \u00ab\u0435\u0441\u043b\u0438 Google \u2014 \u0442\u043e \u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u2014 \u0442\u043e \u0438\u043d\u0430\u0447\u0435, \u0435\u0441\u043b\u0438 \u042f\u043d\u0434\u0435\u043a\u0441 \u2014 \u0442\u043e \u0435\u0449\u0451 \u043a\u0430\u043a-\u0442\u043e\u00bb, \u0443 \u043d\u0430\u0441 \u0434\u0432\u0430 \u0443\u0440\u043e\u0432\u043d\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438.Strategy \u2014 \u044d\u0442\u043e \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b. \u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 CRUD \u043d\u0430\u0434 \u0444\u0430\u0439\u043b\u043e\u043c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435: \u0441\u043e\u0437\u0434\u0430\u0442\u044c, \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c, \u0443\u0434\u0430\u043b\u0438\u0442\u044c, \u043f\u043b\u044e\u0441 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443, \u043f\u043b\u044e\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c URL \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441\u0432\u043e\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f:class StorageStrategyBase(ABC):    strategy_type: str = &#171;&#187;    @abstractmethod    async def create_file(self, storage, attachment, content, filename, &#8230;): &#8230;    @abstractmethod    async def read_file(self, storage, attachment) -&gt; bytes | None: &#8230;    @abstractmethod    async def update_file(self, storage, attachment, content=None, &#8230;): &#8230;    @abstractmethod    async def delete_file(self, storage, attachment) -&gt; bool: &#8230;    @abstractmethod    async def create_folder(self, storage, folder_name, parent_id=None, &#8230;): &#8230;    @abstractmethod    async def validate_connection(self, storage) -&gt; bool: &#8230;    @abstractmethod    async def get_file_url(self, storage, attachment) -&gt; str | None: &#8230;\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0439 \u0443\u0436\u0435 \u0442\u0440\u0438: FileStoreStrategy (\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0430\u043f\u043a\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0434\u0435\u0444\u043e\u043b\u0442), GoogleDriveStrategy \u0438 YandexDiskStrategy. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u2014 \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u043e\u0447\u043a\u0430 \u0432 app.py \u043c\u043e\u0434\u0443\u043b\u044f:register_strategy(GoogleDriveStrategy)Route \u2014 \u044d\u0442\u043e \u043a\u0443\u0434\u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b \u0438 \u043f\u043e\u0434 \u043a\u0430\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c. \u041c\u0430\u0440\u0448\u0440\u0443\u0442 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, \u043a\u0430\u043a \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f create_file, \u0435\u043c\u0443 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e. \u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f \u0441\u0434\u0435\u043b\u043a\u0438 Sale#123 \u0444\u0430\u0439\u043b\u044b \u043f\u043e\u043f\u0430\u043b\u0438 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 Sales Orders\/SO-0000123-\u0418\u0432\u0430\u043d\u043e\u0432\/, \u0430 \u043d\u0435 \u0432 \u043f\u043b\u043e\u0441\u043a\u0443\u044e \u043a\u0443\u0447\u0443. \u041f\u0440\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u0447\u0443\u0442\u044c \u043d\u0438\u0436\u0435.\u042d\u0442\u0438 \u0434\u0432\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0436\u0438\u0432\u0443\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e. \u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e \u043f\u0438\u0448\u0443\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u043e\u0434 \u043e\u0431\u043b\u0430\u043a\u043e \u0438 \u0437\u0430\u0431\u044b\u0432\u0430\u044e\u0442. \u041c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0430\u0434\u043c\u0438\u043d \u043a\u043b\u0438\u043a\u0430\u043c\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.\u0421\u0432\u044f\u0437\u043a\u0430 Strategy + Route: \u0447\u0442\u043e \u043a\u0443\u0434\u0430 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0438 \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0442\u044c.\u041c\u043e\u0434\u0443\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449: \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 Google \u0438 \u042f\u043d\u0434\u0435\u043a\u0441\u0430\u0421\u043d\u0430\u0440\u0443\u0436\u0438 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0443\u043d\u043a\u0442 \u0432 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c \u00ab\u0422\u0438\u043f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u00bb: FileStore, Google Drive, Yandex Disk. \u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 attachments_google \u0438 attachments_yandex.\u041a\u0430\u0436\u0434\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0451\u0445 \u0447\u0430\u0441\u0442\u0435\u0439:Mixin \u2014 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u044c AttachmentStorage, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u0441\u0432\u043e\u0438 \u043f\u043e\u043b\u044f (google_credentials, google_team_id, yandex_access_token, yandex_refresh_token \u0438 \u0442. \u0434.). \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440 @extend, \u0431\u0435\u0437 \u043f\u0440\u0430\u0432\u043e\u043a \u044f\u0434\u0440\u0430.Strategy \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0432\u044b\u0448\u0435 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e API.OAuth-\u0440\u043e\u0443\u0442\u0435\u0440 \u2014 \u0434\u0432\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430: \/{provider}\/auth\/{storage_id} (\u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 authorization_url) \u0438 \/{provider}\/callback (\u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u043d\u0430 \u0442\u043e\u043a\u0435\u043d\u044b, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0432 storage).\u0412 \u043a\u043e\u0434\u0435 \u044d\u0442\u043e \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u043e \u0438 \u0437\u0435\u0440\u043a\u0430\u043b\u044c\u043d\u043e \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 access-\u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u042f\u043d\u0434\u0435\u043a\u0441\u0435:async def _refresh_access_token(self, storage):    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:        response = await client.post(OAUTH_TOKEN_URL, data={            &#171;grant_type&#187;: &#171;refresh_token&#187;,            &#171;refresh_token&#187;: storage.yandex_refresh_token,            &#171;client_id&#187;: storage.yandex_client_id,            &#171;client_secret&#187;: storage.yandex_client_secret,        })    # &#8230;\u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0435 \u0442\u043e\u043a\u0435\u043d\u044b \u0432 storage\u0412 Google \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u0438\u0431\u0435 google-auth, \u043d\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0442\u043e\u0442 \u0436\u0435: \u043f\u0440\u0438 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d \u043c\u043e\u043b\u0447\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u0432 \u0411\u0414 \u043f\u0438\u0448\u0443\u0442\u0441\u044f \u0441\u0432\u0435\u0436\u0438\u0435 credentials, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u0435\u0442. \u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 Google Drive \u0432 FARA CRM.\u0424\u043e\u0440\u043c\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a.\u0427\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c FARA, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438, \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e \u043d\u0435 \u0432\u0438\u0434\u0438\u0442, \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0444\u0430\u0439\u043b. \u041f\u0440\u0435\u0432\u044c\u044e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0444\u0430\u0439\u043b \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0441\u0441\u044b\u043b\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u2014 \u0430 \u0432\u043d\u0443\u0442\u0440\u0438 CRM, \u043f\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u0438\u043b\u0438 \u0438\u0437 \u043e\u0431\u043b\u0430\u043a\u0430, \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u043d\u0430\u043c \u0431\u044b\u043b \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u0435\u043d: \u043e\u0431\u043b\u0430\u043a\u043e \u2014 \u044d\u0442\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u0430 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u00ab\u0432\u0442\u043e\u0440\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u0439\u00bb.\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u2014 \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0444\u0438\u0447\u0430, \u0440\u0430\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u043e\u0438\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435\u041c\u0430\u0440\u0448\u0440\u0443\u0442 (AttachmentRoute) \u2014 \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0434\u0432\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 CRM: \u043a\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043a\u043e\u0440\u043d\u0435\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u044d\u0442\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435 \u0438 \u043a\u0430\u043a \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0451.\u041c\u043e\u0434\u0435\u043b\u044c \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e:class AttachmentRoute(DotModel):    name: str           # \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f    model: str | None   # &#8216;sale&#8217;, &#8216;lead&#8217;, None \u0434\u043b\u044f fallback-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430    priority: int       # \u0432\u044b\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u2014 \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442    pattern_root: str   # \u0448\u0430\u0431\u043b\u043e\u043d \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 \u043c\u043e\u0434\u0435\u043b\u0438    pattern_record: str # \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0430\u043f\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0438    flat: bool          # \u0431\u0435\u0437 \u043f\u043e\u0434\u043f\u0430\u043f\u043e\u043a \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c?    filter: list | None # \u0444\u0438\u043b\u044c\u0442\u0440 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (DSL CRM)    storage_id: M2O     # \u043a \u043a\u0430\u043a\u043e\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f    active: bool\u0412 pattern_root \u0438 pattern_record \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435: \u0438\u043c\u044f \u043c\u043e\u0434\u0435\u043b\u0438, ID, \u043b\u044e\u0431\u044b\u0435 \u043f\u043e\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438, \u043f\u043b\u044e\u0441 \u0445\u0435\u043b\u043f\u0435\u0440 zfill (\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0443\u043b\u044f\u043c\u0438 \u0434\u043e \u0441\u0435\u043c\u0438 \u0437\u043d\u0430\u043a\u043e\u0432). \u041f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440:pattern_root   = &#171;Sales Orders&#187;pattern_record = &#171;SO-{zfill(id)}-{name}&#187;\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:Drive\/\u2514\u2500\u2500 Sales Orders\/    \u251c\u2500\u2500 SO-0000123-\u0418\u0432\u0430\u043d\u043e\u0432\/    \u2502   \u251c\u2500\u2500 contract.pdf    \u2502   \u2514\u2500\u2500 invoice.pdf    \u2514\u2500\u2500 SO-0000124-\u041f\u0435\u0442\u0440\u043e\u0432\/        \u2514\u2500\u2500 proposal.docx\u042d\u0442\u043e \u0443\u0436\u0435 \u043f\u0430\u043f\u043a\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0443 \u2014 \u0438 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0434\u043b\u044f \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430, \u043d\u0435 \u0437\u043d\u0430\u044e\u0449\u0435\u0433\u043e CRM. \u041d\u0435 attachments_42_storage_3_file_uuid.bin, \u0430 SO-0000123-\u0418\u0432\u0430\u043d\u043e\u0432\/contract.pdf.\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430: \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u043a\u0430\u043a \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435.\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u0432 Google Drive, \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443.\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b, \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 fallback\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u043d\u0430 \u043e\u0434\u043d\u0443 \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:\u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u00abVIP-\u043a\u043b\u0438\u0435\u043d\u0442\u044b\u00bb \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c [(&#171;client_tier&#187;, &#171;=&#187;, &#171;vip&#187;)], \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 100, \u043f\u0430\u0442\u0442\u0435\u0440\u043d VIP\/{name};\u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c sale, \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 10;fallback-\u043c\u0430\u0440\u0448\u0440\u0443\u0442 (model = None) \u2014 \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e, \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u043f\u0430\u043b\u043e \u043d\u0438 \u0432 \u043e\u0434\u0438\u043d \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0439.\u041b\u043e\u0433\u0438\u043a\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430:@classmethodasync def get_route_for_attachment(cls, res_model, res_id):    if res_model and res_id:        # 1) \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043f\u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u2014 \u043f\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443        specific = await cls.search(filter=[            (&#171;active&#187;, &#171;=&#187;, True),            (&#171;model&#187;, &#171;=&#187;, res_model),        ], sort=&#187;priority&#187;, order=&#187;DESC&#187;)        for route in specific:            if await route._check_record_in_filter(res_id):                return route    # 2) fallback (model=None) \u2014 \u043f\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0443    fallback = await cls.search(filter=[        (&#171;active&#187;, &#171;=&#187;, True),        (&#171;model&#187;, &#171;=&#187;, None),    ], sort=&#187;priority&#187;, order=&#187;DESC&#187;)    return fallback[0] if fallback else None\u0422\u043e \u0435\u0441\u0442\u044c \u00ab\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u00bb \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u0431\u0435\u0436\u0434\u0430\u0435\u0442 fallback \u2014 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0443 fallback \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0432\u044b\u0448\u0435. \u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u043e\u0434\u0438\u043d \u0430\u0434\u043c\u0438\u043d \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0449\u0438\u0439 fallback \u043d\u0430 \u0432\u0441\u044e CRM, \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b, \u0438 \u043e\u043d\u0438 \u043d\u0435 \u0434\u0435\u0440\u0443\u0442\u0441\u044f.\u0422\u0440\u0438 \u0442\u0438\u043f\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438\u0412 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0444\u043b\u0430\u0433\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e CRM \u0438 \u043e\u0431\u043b\u0430\u043a\u043e \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u0430\u043c\u0438:enable_realtime      = Boolean(default=False, &#8230;)  # \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438enable_one_way_cron  = Boolean(default=False, &#8230;)  # CRM \u2192 \u043e\u0431\u043b\u0430\u043a\u043e, \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044eenable_two_way_cron  = Boolean(default=False, &#8230;)  # CRM \u2194 \u043e\u0431\u043b\u0430\u043a\u043e, \u043f\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044e\u0418 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u2014 \u043a\u0430\u043a \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f:file_missing_cloud   # \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0435\u0441\u0442\u044c \u0432 CRM, \u043d\u043e \u043d\u0435\u0442 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435file_missing_local   # \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0435\u0441\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u043a\u0435, \u043d\u043e \u043d\u0435\u0442 \u0432 CRMRealtime (\u043e\u043d\u043b\u0430\u0439\u043d). \u0424\u0430\u0439\u043b \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0432 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0441\u0434\u0435\u043b\u043a\u0438 \u2192 &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-478018","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=478018"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478018\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=478018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=478018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=478018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}