- Добавлен group
  - Все эндпоинты связанные с генерацией перенесены в generator
  - Другие правки
This commit is contained in:
Danil Solovyov 2022-11-12 15:24:48 +05:00
parent 3d93651f1d
commit 6c3e496dea
68 changed files with 900 additions and 61283 deletions

@ -1 +0,0 @@
D-pQFb0jbC3C5gdjuyP3YFabZW-uf9P5CTuGBZcSXgk.R60lE_tZjdCU5kHqzb9jqcJRgM710MzR1I3Gbc654EQ

@ -1 +0,0 @@
OxqCK9E4XVUNSU9BhiagctEC43n5aluXb3h14ODYwDo.R60lE_tZjdCU5kHqzb9jqcJRgM710MzR1I3Gbc654EQ

@ -0,0 +1 @@
UsuZw8fFY2WlbsVOf_8toqgs_KkNkKttA7Z3LjU10YA.R60lE_tZjdCU5kHqzb9jqcJRgM710MzR1I3Gbc654EQ

@ -0,0 +1 @@
eZnJdCKTZLB8b9M4buK_b-kNgyhFoJm9EakfR247UZQ.R60lE_tZjdCU5kHqzb9jqcJRgM710MzR1I3Gbc654EQ

@ -2,7 +2,6 @@ FROM alpine
EXPOSE 80
ADD amocrm_templategen_back /
ADD static static
ADD assets assets
ADD .well-known .well-known
ADD tmp tmp
ENV DOMAIN=tempgen.pena.digital

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,485 +0,0 @@
/*!
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,482 +0,0 @@
/*!
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

11266
assets/css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

5046
assets/js/bootstrap.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,338 +0,0 @@
/*!
SerializeJSON jQuery plugin.
https://github.com/marioizquierdo/jquery.serializeJSON
version 3.2.1 (Feb, 2021)
Copyright (c) 2012-2021 Mario Izquierdo
Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*/
(function (factory) {
/* global define, require, module */
if (typeof define === "function" && define.amd) { // AMD. Register as an anonymous module.
define(["jquery"], factory);
} else if (typeof exports === "object") { // Node/CommonJS
var jQuery = require("jquery");
module.exports = factory(jQuery);
} else { // Browser globals (zepto supported)
factory(window.jQuery || window.Zepto || window.$); // Zepto supported on browsers as well
}
}(function ($) {
"use strict";
var rCRLF = /\r?\n/g;
var rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i;
var rsubmittable = /^(?:input|select|textarea|keygen)/i;
var rcheckableType = /^(?:checkbox|radio)$/i;
$.fn.serializeJSON = function (options) {
var f = $.serializeJSON;
var $form = this; // NOTE: the set of matched elements is most likely a form, but it could also be a group of inputs
var opts = f.setupOpts(options); // validate options and apply defaults
var typeFunctions = $.extend({}, opts.defaultTypes, opts.customTypes);
// Make a list with {name, value, el} for each input element
var serializedArray = f.serializeArray($form, opts);
// Convert the serializedArray into a serializedObject with nested keys
var serializedObject = {};
$.each(serializedArray, function (_i, obj) {
var nameSansType = obj.name;
var type = $(obj.el).attr("data-value-type");
if (!type && !opts.disableColonTypes) { // try getting the type from the input name
var p = f.splitType(obj.name); // "foo:string" => ["foo", "string"]
nameSansType = p[0];
type = p[1];
}
if (type === "skip") {
return; // ignore fields with type skip
}
if (!type) {
type = opts.defaultType; // "string" by default
}
var typedValue = f.applyTypeFunc(obj.name, obj.value, type, obj.el, typeFunctions); // Parse type as string, number, etc.
if (!typedValue && f.shouldSkipFalsy(obj.name, nameSansType, type, obj.el, opts)) {
return; // ignore falsy inputs if specified in the options
}
var keys = f.splitInputNameIntoKeysArray(nameSansType);
f.deepSet(serializedObject, keys, typedValue, opts);
});
return serializedObject;
};
// Use $.serializeJSON as namespace for the auxiliar functions
// and to define defaults
$.serializeJSON = {
defaultOptions: {}, // reassign to override option defaults for all serializeJSON calls
defaultBaseOptions: { // do not modify, use defaultOptions instead
checkboxUncheckedValue: undefined, // to include that value for unchecked checkboxes (instead of ignoring them)
useIntKeysAsArrayIndex: false, // name="foo[2]" value="v" => {foo: [null, null, "v"]}, instead of {foo: ["2": "v"]}
skipFalsyValuesForTypes: [], // skip serialization of falsy values for listed value types
skipFalsyValuesForFields: [], // skip serialization of falsy values for listed field names
disableColonTypes: false, // do not interpret ":type" suffix as a type
customTypes: {}, // extends defaultTypes
defaultTypes: {
"string": function(str) { return String(str); },
"number": function(str) { return Number(str); },
"boolean": function(str) { var falses = ["false", "null", "undefined", "", "0"]; return falses.indexOf(str) === -1; },
"null": function(str) { var falses = ["false", "null", "undefined", "", "0"]; return falses.indexOf(str) === -1 ? str : null; },
"array": function(str) { return JSON.parse(str); },
"object": function(str) { return JSON.parse(str); },
"skip": null // skip is a special type used to ignore fields
},
defaultType: "string",
},
// Validate and set defaults
setupOpts: function(options) {
if (options == null) options = {};
var f = $.serializeJSON;
// Validate
var validOpts = [
"checkboxUncheckedValue",
"useIntKeysAsArrayIndex",
"skipFalsyValuesForTypes",
"skipFalsyValuesForFields",
"disableColonTypes",
"customTypes",
"defaultTypes",
"defaultType"
];
for (var opt in options) {
if (validOpts.indexOf(opt) === -1) {
throw new Error("serializeJSON ERROR: invalid option '" + opt + "'. Please use one of " + validOpts.join(", "));
}
}
// Helper to get options or defaults
return $.extend({}, f.defaultBaseOptions, f.defaultOptions, options);
},
// Just like jQuery's serializeArray method, returns an array of objects with name and value.
// but also includes the dom element (el) and is handles unchecked checkboxes if the option or data attribute are provided.
serializeArray: function($form, opts) {
if (opts == null) { opts = {}; }
var f = $.serializeJSON;
return $form.map(function() {
var elements = $.prop(this, "elements"); // handle propHook "elements" to filter or add form elements
return elements ? $.makeArray(elements) : this;
}).filter(function() {
var $el = $(this);
var type = this.type;
// Filter with the standard W3C rules for successful controls: http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
return this.name && // must contain a name attribute
!$el.is(":disabled") && // must not be disable (use .is(":disabled") so that fieldset[disabled] works)
rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && // only serialize submittable fields (and not buttons)
(this.checked || !rcheckableType.test(type) || f.getCheckboxUncheckedValue($el, opts) != null); // skip unchecked checkboxes (unless using opts)
}).map(function(_i, el) {
var $el = $(this);
var val = $el.val();
var type = this.type; // "input", "select", "textarea", "checkbox", etc.
if (val == null) {
return null;
}
if (rcheckableType.test(type) && !this.checked) {
val = f.getCheckboxUncheckedValue($el, opts);
}
if (isArray(val)) {
return $.map(val, function(val) {
return { name: el.name, value: val.replace(rCRLF, "\r\n"), el: el };
} );
}
return { name: el.name, value: val.replace(rCRLF, "\r\n"), el: el };
}).get();
},
getCheckboxUncheckedValue: function($el, opts) {
var val = $el.attr("data-unchecked-value");
if (val == null) {
val = opts.checkboxUncheckedValue;
}
return val;
},
// Parse value with type function
applyTypeFunc: function(name, strVal, type, el, typeFunctions) {
var typeFunc = typeFunctions[type];
if (!typeFunc) { // quick feedback to user if there is a typo or missconfiguration
throw new Error("serializeJSON ERROR: Invalid type " + type + " found in input name '" + name + "', please use one of " + objectKeys(typeFunctions).join(", "));
}
return typeFunc(strVal, el);
},
// Splits a field name into the name and the type. Examples:
// "foo" => ["foo", ""]
// "foo:boolean" => ["foo", "boolean"]
// "foo[bar]:null" => ["foo[bar]", "null"]
splitType : function(name) {
var parts = name.split(":");
if (parts.length > 1) {
var t = parts.pop();
return [parts.join(":"), t];
} else {
return [name, ""];
}
},
// Check if this input should be skipped when it has a falsy value,
// depending on the options to skip values by name or type, and the data-skip-falsy attribute.
shouldSkipFalsy: function(name, nameSansType, type, el, opts) {
var skipFromDataAttr = $(el).attr("data-skip-falsy");
if (skipFromDataAttr != null) {
return skipFromDataAttr !== "false"; // any value is true, except the string "false"
}
var optForFields = opts.skipFalsyValuesForFields;
if (optForFields && (optForFields.indexOf(nameSansType) !== -1 || optForFields.indexOf(name) !== -1)) {
return true;
}
var optForTypes = opts.skipFalsyValuesForTypes;
if (optForTypes && optForTypes.indexOf(type) !== -1) {
return true;
}
return false;
},
// Split the input name in programatically readable keys.
// Examples:
// "foo" => ["foo"]
// "[foo]" => ["foo"]
// "foo[inn][bar]" => ["foo", "inn", "bar"]
// "foo[inn[bar]]" => ["foo", "inn", "bar"]
// "foo[inn][arr][0]" => ["foo", "inn", "arr", "0"]
// "arr[][val]" => ["arr", "", "val"]
splitInputNameIntoKeysArray: function(nameWithNoType) {
var keys = nameWithNoType.split("["); // split string into array
keys = $.map(keys, function (key) { return key.replace(/\]/g, ""); }); // remove closing brackets
if (keys[0] === "") { keys.shift(); } // ensure no opening bracket ("[foo][inn]" should be same as "foo[inn]")
return keys;
},
// Set a value in an object or array, using multiple keys to set in a nested object or array.
// This is the main function of the script, that allows serializeJSON to use nested keys.
// Examples:
//
// deepSet(obj, ["foo"], v) // obj["foo"] = v
// deepSet(obj, ["foo", "inn"], v) // obj["foo"]["inn"] = v // Create the inner obj["foo"] object, if needed
// deepSet(obj, ["foo", "inn", "123"], v) // obj["foo"]["arr"]["123"] = v //
//
// deepSet(obj, ["0"], v) // obj["0"] = v
// deepSet(arr, ["0"], v, {useIntKeysAsArrayIndex: true}) // arr[0] = v
// deepSet(arr, [""], v) // arr.push(v)
// deepSet(obj, ["arr", ""], v) // obj["arr"].push(v)
//
// arr = [];
// deepSet(arr, ["", v] // arr => [v]
// deepSet(arr, ["", "foo"], v) // arr => [v, {foo: v}]
// deepSet(arr, ["", "bar"], v) // arr => [v, {foo: v, bar: v}]
// deepSet(arr, ["", "bar"], v) // arr => [v, {foo: v, bar: v}, {bar: v}]
//
deepSet: function (o, keys, value, opts) {
if (opts == null) { opts = {}; }
var f = $.serializeJSON;
if (isUndefined(o)) { throw new Error("ArgumentError: param 'o' expected to be an object or array, found undefined"); }
if (!keys || keys.length === 0) { throw new Error("ArgumentError: param 'keys' expected to be an array with least one element"); }
var key = keys[0];
// Only one key, then it's not a deepSet, just assign the value in the object or add it to the array.
if (keys.length === 1) {
if (key === "") { // push values into an array (o must be an array)
o.push(value);
} else {
o[key] = value; // keys can be object keys (strings) or array indexes (numbers)
}
return;
}
var nextKey = keys[1]; // nested key
var tailKeys = keys.slice(1); // list of all other nested keys (nextKey is first)
if (key === "") { // push nested objects into an array (o must be an array)
var lastIdx = o.length - 1;
var lastVal = o[lastIdx];
// if the last value is an object or array, and the new key is not set yet
if (isObject(lastVal) && isUndefined(f.deepGet(lastVal, tailKeys))) {
key = lastIdx; // then set the new value as a new attribute of the same object
} else {
key = lastIdx + 1; // otherwise, add a new element in the array
}
}
if (nextKey === "") { // "" is used to push values into the nested array "array[]"
if (isUndefined(o[key]) || !isArray(o[key])) {
o[key] = []; // define (or override) as array to push values
}
} else {
if (opts.useIntKeysAsArrayIndex && isValidArrayIndex(nextKey)) { // if 1, 2, 3 ... then use an array, where nextKey is the index
if (isUndefined(o[key]) || !isArray(o[key])) {
o[key] = []; // define (or override) as array, to insert values using int keys as array indexes
}
} else { // nextKey is going to be the nested object's attribute
if (isUndefined(o[key]) || !isObject(o[key])) {
o[key] = {}; // define (or override) as object, to set nested properties
}
}
}
// Recursively set the inner object
f.deepSet(o[key], tailKeys, value, opts);
},
deepGet: function (o, keys) {
var f = $.serializeJSON;
if (isUndefined(o) || isUndefined(keys) || keys.length === 0 || (!isObject(o) && !isArray(o))) {
return o;
}
var key = keys[0];
if (key === "") { // "" means next array index (used by deepSet)
return undefined;
}
if (keys.length === 1) {
return o[key];
}
var tailKeys = keys.slice(1);
return f.deepGet(o[key], tailKeys);
}
};
// polyfill Object.keys to get option keys in IE<9
var objectKeys = function(obj) {
if (Object.keys) {
return Object.keys(obj);
} else {
var key, keys = [];
for (key in obj) { keys.push(key); }
return keys;
}
};
var isObject = function(obj) { return obj === Object(obj); }; // true for Objects and Arrays
var isUndefined = function(obj) { return obj === void 0; }; // safe check for undefined values
var isValidArrayIndex = function(val) { return /^[0-9]+$/.test(String(val)); }; // 1,2,3,4 ... are valid array indexes
var isArray = Array.isArray || function(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; };
}));

@ -48,13 +48,14 @@ func (dal *PostgresDAL) Disconnect() {
}
type MongoDAL struct {
conn *mongo.Client
logger *zap.Logger
User *mongos.User
YaDisk *mongos.YaDisk
GDisk *mongos.GDisk
Amo *mongos.Amo
Template *mongos.Template
conn *mongo.Client
logger *zap.Logger
User *mongos.User
YaDisk *mongos.YaDisk
GDisk *mongos.GDisk
Amo *mongos.Amo
Template *mongos.Template
TemplateGroup *mongos.TemplateGroup
}
func InitMongoDAL(ctx context.Context, dbURL, dbTable string, logger *zap.Logger) (*MongoDAL, error) {
@ -74,13 +75,14 @@ func InitMongoDAL(ctx context.Context, dbURL, dbTable string, logger *zap.Logger
}
dal := &MongoDAL{
conn: conn,
logger: logger,
User: mongos.InitUser(conn.Database(dbTable), logger),
YaDisk: mongos.InitYaDisk(conn.Database(dbTable), logger),
GDisk: mongos.InitGDisk(conn.Database(dbTable), logger),
Amo: mongos.InitAmo(conn.Database(dbTable), logger),
Template: mongos.InitTemplate(conn.Database(dbTable), logger),
conn: conn,
logger: logger,
User: mongos.InitUser(conn.Database(dbTable), logger),
YaDisk: mongos.InitYaDisk(conn.Database(dbTable), logger),
GDisk: mongos.InitGDisk(conn.Database(dbTable), logger),
Amo: mongos.InitAmo(conn.Database(dbTable), logger),
Template: mongos.InitTemplate(conn.Database(dbTable), logger),
TemplateGroup: mongos.InitTemplateGroup(conn.Database(dbTable), logger),
}
_, err = dal.Ping(ctx)

@ -8,11 +8,11 @@ type Template struct {
ID string `bson:"_id,omitempty" json:"id"`
UserID string `bson:"user_id" json:"user_id"`
LeadId string `bson:"lead_id" json:"lead_id"` // AMO lead
Name string `bson:"name" json:"name"` // Название сделки, к которому привязан файл-шаблон
Filename string `bson:"filename" json:"filename"` // Имя файла-шаблона for Yandex Disk
Name string `bson:"name" json:"name"` // Имя файла на диске
File string `bson:"file" json:"file"` // Имя файла-шаблона for Yandex Disk OR File id for Google Drive
StorageID string `bson:"storage_id" json:"storage_id"` // ID of GDisk or YaDisk
StorageType string `bson:"storage_type" json:"storage_type"`
FileID string `bson:"file_id" json:"file_id"` // File id for Google Drive
GroupIDs []string `bson:"group_ids" json:"group_ids"`
IsDeleted bool `bson:"is_deleted" json:"is_deleted"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`

@ -0,0 +1,13 @@
package model
import (
"time"
)
type TemplateGroup struct {
ID string `bson:"_id,omitempty" json:"id"`
UserID string `bson:"user_id" json:"user_id"`
Name string `bson:"name" json:"name"`
CreatedAt time.Time `bson:"created_at" json:"created_at"`
UpdatedAt time.Time `bson:"updated_at" json:"updated_at"`
}

@ -122,8 +122,6 @@ func (d *Template) GetByNameAndUserID(ctx context.Context, name, userID string)
}
}
fmt.Println("RESUKLT", result)
d.logger.Info("InfoGetTemplate", zap.String("id", result.ID))
return &result, nil
@ -209,6 +207,129 @@ func (d *Template) GetListByUserIDAndStorageType(ctx context.Context, userID, st
return result, nil
}
func (d *Template) GetListByGroupID(ctx context.Context, groupID, userID string) ([]model.Template, error) {
if groupID == "" {
err := errors.New("group_id required")
d.logger.Error("ErrorGetTemplateList", zap.Error(err))
return nil, err
}
filter := bson.M{"group_ids": groupID, "user_id": userID}
cur, err := d.coll.Find(ctx, filter)
if err != nil {
d.logger.Error("ErrorGetTemplateList", zap.Error(err))
return nil, err
}
var result []model.Template
err = cur.All(ctx, &result)
if err != nil {
d.logger.Error("ErrorGetTemplateList", zap.Error(err))
return nil, err
}
return result, nil
}
func (d *Template) PushGroup(ctx context.Context, id, groupID, userID string) error {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
d.logger.Error("ErrorPushTemplateGroup", zap.Error(err))
return err
}
if groupID == "" {
err = errors.New("group_id required")
d.logger.Error("ErrorPushTemplateGroup", zap.Error(err))
return err
}
filter := bson.M{"_id": objID}
if userID != "" {
filter["user_id"] = userID
}
update := bson.M{
"$addToSet": bson.M{"group_ids": groupID},
"$set": bson.M{"updated_at": time.Now()},
}
_, err = d.coll.UpdateOne(ctx, filter, update)
if err != nil {
d.logger.Error("ErrorPushTemplateGroup", zap.Error(err))
return err
}
d.logger.Info("InfoPushTemplateGroup")
return nil
}
func (d *Template) PullGroup(ctx context.Context, id, groupID, userID string) error {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
d.logger.Error("ErrorPullTemplateGroup", zap.Error(err))
return err
}
if groupID == "" {
err = errors.New("group_id required")
d.logger.Error("ErrorPullTemplateGroup", zap.Error(err))
return err
}
filter := bson.M{"_id": objID}
if userID != "" {
filter["user_id"] = userID
}
update := bson.M{
"$pull": bson.M{"group_ids": groupID},
"$set": bson.M{"updated_at": time.Now()},
}
_, err = d.coll.UpdateOne(ctx, filter, update)
if err != nil {
d.logger.Error("ErrorPullTemplateGroup", zap.Error(err))
return err
}
return nil
}
func (d *Template) DeleteGroupFromAll(ctx context.Context, groupID string) error {
if groupID == "" {
err := errors.New("group_id required")
d.logger.Error("ErrorRemoveTemplateGroup", zap.Error(err))
return err
}
filter := bson.M{"group_ids": groupID}
update := bson.M{
"$pull": bson.M{"group_ids": groupID},
"$set": bson.M{"updated_at": time.Now()},
}
_, err := d.coll.UpdateMany(ctx, filter, update)
if err != nil {
d.logger.Error("ErrorRemoveTemplateGroup", zap.Error(err))
return err
}
return nil
}
func (d *Template) UpdateByID(ctx context.Context, record *model.Template) error {
if record.ID == "" {
err := errors.New("got empty id")
@ -231,8 +352,8 @@ func (d *Template) UpdateByID(ctx context.Context, record *model.Template) error
update["name"] = record.Name
}
if record.Filename != "" {
update["filename"] = record.Filename
if record.File != "" {
update["file"] = record.File
}
if record.LeadId != "" {
@ -247,10 +368,6 @@ func (d *Template) UpdateByID(ctx context.Context, record *model.Template) error
update["storage_type"] = record.StorageType
}
if record.FileID != "" {
update["file_id"] = record.FileID
}
res, err := d.coll.UpdateOne(ctx, filter, bson.D{{"$set", update}})
fmt.Println(update)
@ -279,8 +396,8 @@ func (d *Template) UpdateByLeadID(ctx context.Context, record *model.Template) e
update["name"] = record.Name
}
if record.Filename != "" {
update["filename"] = record.Filename
if record.File != "" {
update["file"] = record.File
}
if record.LeadId != "" {
@ -295,10 +412,6 @@ func (d *Template) UpdateByLeadID(ctx context.Context, record *model.Template) e
update["storage_type"] = record.StorageType
}
if record.FileID != "" {
update["file_id"] = record.FileID
}
_, err := d.coll.UpdateOne(ctx, filter, bson.D{{"$set", update}})
if err != nil {
@ -309,31 +422,6 @@ func (d *Template) UpdateByLeadID(ctx context.Context, record *model.Template) e
return nil
}
func (d *Template) UpdateByNameAndUserID(ctx context.Context, record *model.Template) error {
if record.Name == "" || record.UserID == "" {
err := errors.New("got empty user id or name")
d.logger.Error("ErrorUpdateTemplate", zap.Error(err))
return err
}
filter := bson.M{"name": record.Name, "user_id": record.UserID, "is_deleted": false}
update := bson.M{"updated_at": time.Now()}
if record.Filename != "" {
update["filename"] = record.Filename
}
_, err := d.coll.UpdateOne(ctx, filter, update)
if err != nil {
d.logger.Error("ErrorUpdateTemplate", zap.Error(err))
return err
}
return nil
}
func (d *Template) DeleteByID(ctx context.Context, id string) error {
if id == "" {
err := errors.New("got empty id")
@ -360,23 +448,3 @@ func (d *Template) DeleteByID(ctx context.Context, id string) error {
return nil
}
func (d *Template) DeleteByNameAndUserID(ctx context.Context, name, userID string) error {
if name == "" || userID == "" {
err := errors.New("got empty user id or name")
d.logger.Error("ErrorUpdateTemplate", zap.Error(err))
return err
}
filter := bson.M{"name": name, "user_id": userID, "is_deleted": false}
update := bson.M{"updated_at": time.Now(), "is_deleted": true}
_, err := d.coll.UpdateOne(ctx, filter, bson.D{{"$set", update}})
if err != nil {
d.logger.Error("ErrorDeleteTemplate", zap.Error(err))
return err
}
return nil
}

183
dal/mongos/templateGroup.go Normal file

@ -0,0 +1,183 @@
package mongos
import (
"context"
"errors"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.uber.org/zap"
"time"
)
type TemplateGroup struct {
coll *mongo.Collection
logger *zap.Logger
}
func InitTemplateGroup(db *mongo.Database, logger *zap.Logger) *TemplateGroup {
return &TemplateGroup{coll: db.Collection("template_group"), logger: logger}
}
func (d *TemplateGroup) Insert(ctx context.Context, record *model.TemplateGroup) (string, error) {
now := time.Now()
record.CreatedAt = now
record.UpdatedAt = now
if record.UserID == "" {
err := errors.New("user_id required")
d.logger.Error("ErrorInsertTemplateGroup", zap.Error(err))
return "", err
}
if record.Name == "" {
err := errors.New("name required")
d.logger.Error("ErrorInsertTemplateGroup", zap.Error(err))
return "", err
}
result, err := d.coll.InsertOne(ctx, record)
if err != nil {
d.logger.Error("ErrorInsertTemplateGroup", zap.Error(err))
return "", err
}
id := result.InsertedID.(primitive.ObjectID).Hex()
d.logger.Info("InfoInsertTemplateGroup", zap.String("_id", id))
return id, nil
}
func (d *TemplateGroup) GetByID(ctx context.Context, id string) (*model.TemplateGroup, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
d.logger.Error("ErrorGetTemplateGroup", zap.Error(err))
return nil, err
}
filter := bson.M{"_id": objID}
var result model.TemplateGroup
err = d.coll.FindOne(ctx, filter).Decode(&result)
if err == mongo.ErrNoDocuments {
return nil, nil
} else {
if err != nil {
d.logger.Error("ErrorGetTemplateGroup", zap.Error(err))
return nil, err
}
}
d.logger.Info("ErrorGetTemplateGroup", zap.String("id", result.ID))
return &result, nil
}
func (d *TemplateGroup) GetListByUserID(ctx context.Context, userID string) ([]model.TemplateGroup, error) {
if userID == "" {
err := errors.New("user_id required")
d.logger.Error("ErrorGetListTemplateGroup")
return nil, err
}
filter := bson.M{"user_id": userID}
var result []model.TemplateGroup
cur, err := d.coll.Find(ctx, filter)
if err == mongo.ErrNoDocuments {
return nil, nil
} else {
if err != nil {
d.logger.Error("ErrorGetTemplateGroup", zap.Error(err))
return nil, err
}
}
err = cur.All(ctx, &result)
if err != nil {
d.logger.Error("ErrorGetListTemplateGroup", zap.Error(err))
return nil, err
}
d.logger.Info("InfoGetListTemplateGroup")
return result, err
}
func (d *TemplateGroup) Update(ctx context.Context, record *model.TemplateGroup) error {
objID, err := primitive.ObjectIDFromHex(record.ID)
if err != nil {
d.logger.Error("ErrorUpdateTemplateGroup", zap.Error(err))
return err
}
filter := bson.M{"_id": objID}
if record.UserID != "" {
filter["user_id"] = record.UserID
}
update := bson.M{"updated_at": time.Now()}
if record.Name != "" {
update["name"] = record.Name
}
_, err = d.coll.UpdateOne(ctx, filter, bson.D{{"$set", update}})
if err != nil {
d.logger.Error("ErrorUpdateTemplateGroup")
return err
}
d.logger.Info("InfoUpdateTemplateGroup", zap.String("_id", record.ID))
return nil
}
func (d *TemplateGroup) Delete(ctx context.Context, id string) error {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
d.logger.Error("ErrorDeleteTemplateGroup", zap.Error(err))
return err
}
filter := bson.M{"_id": objID}
_, err = d.coll.DeleteOne(ctx, filter)
if err != nil {
d.logger.Error("ErrorDeleteTemplateGroup", zap.Error(err))
return err
}
return nil
}
func (d *TemplateGroup) DeleteByUserID(ctx context.Context, userID string) error {
if userID == "" {
err := errors.New("user_id required")
d.logger.Error("ErrorDeleteTemplateGroup", zap.Error(err))
return err
}
filter := bson.M{"user_id": userID}
_, err := d.coll.DeleteMany(ctx, filter)
if err != nil {
d.logger.Error("ErrorDeleteTemplateGroup", zap.Error(err))
return err
}
return nil
}

@ -59,7 +59,7 @@ func (ca *ClientApp) GenerateOAuthUrl(userId, redirectUrl string) (string, error
return "", err
}
return ca.Config.AuthCodeURL(state, oauth2.AccessTypeOffline), nil
return ca.Config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.ApprovalForce), nil
}
func (ca *ClientApp) RefreshToken(ctx context.Context, oldToken *oauth2.Token) (*oauth2.Token, error) {
@ -308,7 +308,7 @@ func (c *Client) MakeDefaultDirs(defaultId, defaultName, templateId, templateNam
defaultDir = fl.Files[0]
}
} else {
defaultDir, err = c.Service.Files.Get(templateId).Do()
defaultDir, err = c.Service.Files.Get(defaultId).Do()
if err != nil {
if strings.Contains(err.Error(), "404") {
defaultDir, err = c.PutResources(defaultName, "")

@ -2,16 +2,11 @@ package handlers
import (
"errors"
"fmt"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/amo"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/templategen"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/tools"
"github.com/gorilla/schema"
"golang.org/x/oauth2"
"io"
"net/http"
"net/url"
"strconv"
"time"
)
@ -39,7 +34,7 @@ func (h *Handlers) AmoSaveToken(w http.ResponseWriter, r *http.Request) {
err = schema.NewDecoder().Decode(&req, r.Form)
if err != nil {
h.reportError(w, err, 500)
h.reportError(w, err, http.StatusBadRequest)
return
}
@ -107,138 +102,6 @@ func (h *Handlers) AmoSaveToken(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, state.RedirectUrl, http.StatusPermanentRedirect)
}
func (h *Handlers) AmoWebhook(w http.ResponseWriter, r *http.Request) {
reqBody, err := io.ReadAll(r.Body)
if err != nil {
h.reportError(w, err, 200)
return
}
p, err := url.ParseQuery(string(reqBody))
if err != nil {
h.reportError(w, err, 200)
return
}
leadId := p.Get("leads[status][0][id]")
subdomain := p.Get("account[subdomain]")
accId := p.Get("account[id]")
// Запрашиваем данные по аккаунту
amoData, err := h.dal.Amo.GetByAccountID(r.Context(), accId)
if err != nil {
h.reportError(w, err, 200)
return
}
amoClient, err := h.Amo.NewClient(r.Context(), subdomain, amoData.Token(), "")
if err != nil {
h.reportError(w, err, http.StatusForbidden)
return
}
lead, err := amoClient.GetLeadById(leadId)
if err != nil {
h.reportError(w, err, 200)
return
}
if lead != nil {
// fmt.Printf("Lead RESP:%+v\r\n", lead)
} else {
fmt.Println("Lead empty")
}
dataTemplate := map[string]interface{}{}
// Добавляем Инфо Лида
for k, v := range templategen.AmoLeadFieldsToRuMap(lead) {
dataTemplate[k] = v
}
//filename := fmt.Sprintf("%v", dataTemplate["Filename"])
// Добавялем инфо контактов
contacts := []amo.Contact{}
for _, data := range lead.Embedded.Contacts {
contact, err := amoClient.GetContactById(strconv.Itoa(data.Id))
if err == nil {
contacts = append(contacts, *contact)
} else {
fmt.Println("Something Wrong1:", err)
}
}
dataTemplate["Контакты"] = templategen.AmoContactsFieldsToRuMap(contacts)
// Добавляем инфо компаний
companies := []amo.Company{}
for _, data := range lead.Embedded.Companies {
company, err := amoClient.GetCompanyById(strconv.Itoa(data.Id))
if err == nil {
companies = append(companies, *company)
} else {
fmt.Println("Something Wrong2:", err)
}
}
dataTemplate["Компании"] = templategen.AmoCompaniesFieldsToRuMap(companies)
template, err := h.dal.Template.GetByLeadId(r.Context(), leadId)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
if template == nil {
h.reportError(w, err, http.StatusNotFound)
return
}
switch template.StorageType {
case "gdisk":
gdiskData, err := h.dal.GDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
if gdiskData == nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
client, err := h.GDisk.NewClient(r.Context(), gdiskData.Token())
err = templategen.GDiskGenerateDoc(template, gdiskData.SaveFolderID, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
case "yadisk":
yaDiskData, err := h.dal.YaDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
client, err := h.YaDisk.NewClient(r.Context(), yaDiskData.Token(), "")
err = templategen.YaDiskGenerateDoc(template, yaDiskData.SaveFolder, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
default:
h.reportError(w, errors.New("got unknown storage"), http.StatusInternalServerError)
return
}
sendResponse(w, 200, nil)
}
type RespAmoState struct {
GenCount int `json:"gen_count"`
AuthYandexUrl string `json:"auth_yandex_url"`
@ -249,11 +112,14 @@ type RespAmoState struct {
Delete []int64 `json:"delete"`
}
// AmoState - получить актуальное состояние аккаунта пользователя в Amo
func (h *Handlers) AmoState(w http.ResponseWriter, r *http.Request, redirectUrn string) {
// TODO: get pena jwt
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
@ -274,7 +140,7 @@ func (h *Handlers) AmoState(w http.ResponseWriter, r *http.Request, redirectUrn
"gdisk": gStorages,
}
redirectUri := fmt.Sprintf("https://%v/%v", amoData.Referer, redirectUrn)
redirectUri := "https://" + amoData.Referer + redirectUrn
authYandexUrl, err := h.YaDisk.GenerateOAuthUrl(amoData.UserID, redirectUri)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
@ -300,291 +166,20 @@ func (h *Handlers) AmoState(w http.ResponseWriter, r *http.Request, redirectUrn
sendResponse(w, 200, resp)
}
type ReqAmoGetTemplate struct {
LeadId int64 `json:"lead_id"`
TemplateId string `json:"template_id"`
}
// AmoGetTemplate - получить шаблон по LeadID или template.ID
func (h *Handlers) AmoGetTemplate(w http.ResponseWriter, r *http.Request) {
var req ReqAmoGetTemplate
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.TemplateId == "" && strconv.FormatInt(req.LeadId, 10) == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
var template *model.Template
if req.TemplateId != "" {
template, err = h.dal.Template.GetByID(r.Context(), req.TemplateId)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
}
if strconv.FormatInt(req.LeadId, 10) != "" {
template, err = h.dal.Template.GetByLeadId(r.Context(), strconv.FormatInt(req.LeadId, 10))
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
}
if template == nil {
templateId, err := h.dal.Template.Insert(r.Context(), &model.Template{
UserID: amoData.UserID,
LeadId: strconv.FormatInt(req.LeadId, 10),
})
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
template = &model.Template{ID: templateId}
}
sendResponse(w, 200, template)
}
type ReqAmoSetTemplate struct {
LeadId int64 `json:"lead_id"` // Required for insert/update
TemplateId string `json:"template_id"` // Required for update - может потом удалить ?
Filename string `json:"filename"` // Required for Yandex Disk
FileID string `json:"file_id"` // Required for Google Drive
StorageID string `json:"storage_id"` // Required. id gdisk or yadisk
Storage string `json:"storage"` // Required. yadisk, gdisk - Может удалить потом?
}
type RespAmoSetTemplate struct {
TemplateId string `json:"template_id"`
}
// AmoSetTemplate - устанавливает/обновляет шаблон для сделки
func (h *Handlers) AmoSetTemplate(w http.ResponseWriter, r *http.Request) {
var req ReqAmoSetTemplate
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if strconv.FormatInt(req.LeadId, 10) == "" || req.Storage == "" || req.StorageID == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.Filename == "" && req.FileID == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
// Search/update template
var template *model.Template
update := &model.Template{
ID: req.TemplateId,
UserID: amoData.UserID,
LeadId: strconv.FormatInt(req.LeadId, 10),
Name: "Sample",
Filename: req.Filename,
StorageID: req.StorageID,
FileID: req.FileID,
IsDeleted: false,
}
templateId := ""
if req.TemplateId == "" {
template, err = h.dal.Template.GetByLeadId(r.Context(), strconv.FormatInt(req.LeadId, 10))
fmt.Println(0, template)
if template != nil {
err = h.dal.Template.UpdateByLeadID(r.Context(), update)
} else {
templateId, err = h.dal.Template.Insert(r.Context(), update)
}
} else {
err = h.dal.Template.UpdateByID(r.Context(), update)
}
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
sendResponse(w, 200, RespAmoSetTemplate{templateId})
}
type ReqAmoGenerateDoc struct {
LeadId int64 `json:"lead_id"`
}
func (h *Handlers) AmoGenerateDoc(w http.ResponseWriter, r *http.Request) {
var req ReqAmoGenerateDoc
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
leadId := strconv.FormatInt(req.LeadId, 10)
if leadId == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
template, err := h.dal.Template.GetByLeadId(r.Context(), leadId)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
if template == nil {
h.reportError(w, err, http.StatusNotFound)
return
}
// Получить данные по лиду
amoClient, err := h.Amo.NewClient(r.Context(), amoData.Referer, amoData.Token(), "")
if err != nil {
h.reportError(w, err, http.StatusForbidden)
return
}
lead, err := amoClient.GetLeadById(leadId)
if err != nil {
h.reportError(w, err, 200)
return
}
if lead.Id == 0 {
fmt.Println("Lead empty")
}
dataTemplate := map[string]interface{}{}
// Добавляем Инфо Лида
for k, v := range templategen.AmoLeadFieldsToRuMap(lead) {
dataTemplate[k] = v
}
//filename := fmt.Sprintf("%v_%v_%v.docx", req.Filename, amoData.UserID, time.Now().Unix())
// Добавялем инфо контактов
contacts := []amo.Contact{}
for _, data := range lead.Embedded.Contacts {
contact, err := amoClient.GetContactById(strconv.Itoa(data.Id))
if err == nil {
contacts = append(contacts, *contact)
} else {
fmt.Println("Something Wrong1:", err)
}
}
dataTemplate["Контакты"] = templategen.AmoContactsFieldsToRuMap(contacts)
// Добавляем инфо компаний
companies := []amo.Company{}
for _, data := range lead.Embedded.Companies {
company, err := amoClient.GetCompanyById(strconv.Itoa(data.Id))
if err == nil {
companies = append(companies, *company)
} else {
fmt.Println("Something Wrong2:", err)
}
}
dataTemplate["Компании"] = templategen.AmoCompaniesFieldsToRuMap(companies)
switch template.StorageType {
case "gdisk":
gdiskData, err := h.dal.GDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
if gdiskData == nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
client, err := h.GDisk.NewClient(r.Context(), gdiskData.Token())
err = templategen.GDiskGenerateDoc(template, gdiskData.SaveFolderID, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
case "yadisk":
yaDiskData, err := h.dal.YaDisk.GetByID(r.Context(), template.StorageID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
client, err := h.YaDisk.NewClient(r.Context(), yaDiskData.Token(), "")
err = templategen.YaDiskGenerateDoc(template, yaDiskData.SaveFolder, client, dataTemplate)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
default:
h.reportError(w, errors.New("got unknown storage"), http.StatusInternalServerError)
return
}
sendResponse(w, http.StatusOK, nil)
}
type ReqAmoAccessRules struct {
Visibility []int64 `json:"visibility"`
Creation []int64 `json:"creation"`
Delete []int64 `json:"delete"`
}
// AmoAccessRules - задать правила для пользователя
func (h *Handlers) AmoAccessRules(w http.ResponseWriter, r *http.Request) {
var req ReqAmoAccessRules
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}

@ -2,62 +2,95 @@ package handlers
import (
"errors"
"fmt"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
"net/http"
"strconv"
)
type RespTemplateNew struct {
Name string `json:"name"`
Filename string `json:"filename"`
Storage string `json:"storage"`
type ReqTemplateSet struct {
LeadId int64 `json:"lead_id"` // Required for insert/update
TemplateId string `json:"template_id"` // Required for update - может потом удалить ?
File string `json:"file"` // Required.
StorageID string `json:"storage_id"` // Required. id gdisk or yadisk
Storage string `json:"storage"` // Required. yadisk, gdisk - Может удалить потом?
}
func (h *Handlers) TemplateNew(w http.ResponseWriter, r *http.Request) {
var resp RespTemplateNew
type RespTemplateSet struct {
TemplateId string `json:"template_id"`
}
user := getJwtUser(r)
// TemplateSet - устанавливает/обновляет шаблон для сделки
func (h *Handlers) TemplateSet(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateSet
if user == nil {
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&resp, r)
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if resp.Name == "" || resp.Filename == "" {
err = errors.New("got empty name or filename")
h.reportError(w, err, http.StatusBadRequest)
if req.LeadId <= 0 || req.Storage == "" || req.StorageID == "" {
h.reportError(w, errors.New("bad request"), http.StatusBadRequest)
return
}
_, err = h.dal.Template.Insert(r.Context(), &model.Template{
UserID: user.UserID,
Name: resp.Name,
Filename: resp.Filename,
StorageID: resp.Storage,
if req.File == "" {
h.reportError(w, errors.New("file required"), http.StatusBadRequest)
return
}
// Search/update template
var template *model.Template
update := &model.Template{
ID: req.TemplateId,
UserID: amoData.UserID,
LeadId: strconv.FormatInt(req.LeadId, 10),
Name: "Sample",
File: req.File,
StorageID: req.StorageID,
IsDeleted: false,
})
}
templateId := ""
if req.TemplateId == "" {
template, err = h.dal.Template.GetByLeadId(r.Context(), strconv.FormatInt(req.LeadId, 10))
fmt.Println(0, template)
if template != nil {
err = h.dal.Template.UpdateByLeadID(r.Context(), update)
} else {
templateId, err = h.dal.Template.Insert(r.Context(), update)
}
} else {
err = h.dal.Template.UpdateByID(r.Context(), update)
}
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
sendResponse(w, 200, RespTemplateSet{templateId})
}
func (h *Handlers) TemplateGetListByUser(w http.ResponseWriter, r *http.Request) {
user := getJwtUser(r)
amoData := getAmoByJwt(r)
if user == nil {
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
result, err := h.dal.Template.GetListByUserID(r.Context(), user.UserID)
result, err := h.dal.Template.GetListByUserID(r.Context(), amoData.UserID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
@ -66,82 +99,138 @@ func (h *Handlers) TemplateGetListByUser(w http.ResponseWriter, r *http.Request)
sendResponse(w, 200, result)
}
type RespTemplateGetByID struct {
ID string `json:"id"`
type ReqTemplateGetListByGroup struct {
GroupID string `json:"group_id"`
}
func (h *Handlers) TemplateGetByID(w http.ResponseWriter, r *http.Request) {
var resp RespTemplateGetByID
func (h *Handlers) TemplateGetListByGroup(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateGetListByGroup
user := getJwtUser(r)
amoData := getAmoByJwt(r)
if user == nil {
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&resp, r)
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if resp.ID == "" {
h.reportError(w, err, http.StatusBadRequest)
if req.GroupID == "" {
h.reportError(w, errors.New("group_id required"), http.StatusBadRequest)
return
}
result, err := h.dal.Template.GetByID(r.Context(), resp.ID)
resp, err := h.dal.Template.GetListByGroupID(r.Context(), req.GroupID, amoData.UserID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
sendResponse(w, 200, result)
sendResponse(w, http.StatusOK, resp)
}
type RespTemplateUpdate struct {
ID string `json:"id"`
Name string `json:"name"`
TemplateFilename string `json:"template_filename"`
type ReqTemplateGet struct {
LeadId int64 `json:"lead_id"`
TemplateId string `json:"template_id"`
}
func (h *Handlers) TemplateGet(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateGet
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.TemplateId == "" && strconv.FormatInt(req.LeadId, 10) == "" {
h.reportError(w, err, http.StatusBadRequest)
return
}
var template *model.Template
if req.TemplateId != "" {
template, err = h.dal.Template.GetByID(r.Context(), req.TemplateId)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
}
if strconv.FormatInt(req.LeadId, 10) != "" {
template, err = h.dal.Template.GetByLeadId(r.Context(), strconv.FormatInt(req.LeadId, 10))
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
}
if template == nil {
templateId, err := h.dal.Template.Insert(r.Context(), &model.Template{
UserID: amoData.UserID,
LeadId: strconv.FormatInt(req.LeadId, 10),
})
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
template = &model.Template{ID: templateId}
}
sendResponse(w, 200, template)
}
type ReqTemplateUpdate struct {
ID string `json:"id"` // Template ID
Name string `json:"name"` // Имя сделки
File string `json:"file"` //
}
func (h *Handlers) TemplateUpdate(w http.ResponseWriter, r *http.Request) {
var resp RespTemplateUpdate
var req ReqTemplateUpdate
user := getJwtUser(r)
amoData := getAmoByJwt(r)
if user == nil {
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&resp, r)
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if resp.Name == "" && resp.TemplateFilename == "" {
h.reportError(w, err, http.StatusBadRequest)
if req.ID == "" {
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
return
}
record := &model.Template{
ID: resp.ID,
UserID: user.UserID,
Name: resp.Name,
Filename: resp.TemplateFilename,
ID: req.ID,
UserID: amoData.UserID,
Name: req.Name,
File: req.File,
}
if resp.ID != "" {
err = h.dal.Template.UpdateByID(r.Context(), record)
} else {
err = h.dal.Template.UpdateByNameAndUserID(r.Context(), record)
}
err = h.dal.Template.UpdateByID(r.Context(), record)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
@ -151,38 +240,32 @@ func (h *Handlers) TemplateUpdate(w http.ResponseWriter, r *http.Request) {
sendResponse(w, 200, nil)
}
type RespTemplateDelete struct {
ID string `json:"id"`
Name string `json:"name"`
type ReqTemplateDelete struct {
ID string `json:"id"`
}
func (h *Handlers) TemplateDelete(w http.ResponseWriter, r *http.Request) {
var resp RespTemplateDelete
var req ReqTemplateDelete
user := getJwtUser(r)
amoData := getAmoByJwt(r)
if user == nil {
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&resp, r)
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if resp.ID == "" && resp.Name == "" {
h.reportError(w, err, http.StatusBadRequest)
if req.ID == "" {
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
return
}
if resp.ID != "" {
err = h.dal.Template.DeleteByID(r.Context(), resp.ID)
} else {
err = h.dal.Template.DeleteByNameAndUserID(r.Context(), resp.Name, user.UserID)
}
err = h.dal.Template.DeleteByID(r.Context(), req.ID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
@ -192,13 +275,13 @@ func (h *Handlers) TemplateDelete(w http.ResponseWriter, r *http.Request) {
sendResponse(w, 200, nil)
}
type RespTemplateInit struct {
type ReqTemplateInit struct {
EventName string `json:"event_name"`
Data map[string]interface{} `json:"data"`
}
func (h *Handlers) TemplateInit(w http.ResponseWriter, r *http.Request) {
//var resp RespTemplateInit
//var req ReqTemplateInit
//
//user := getJwtUser(r)
//
@ -215,7 +298,7 @@ func (h *Handlers) TemplateInit(w http.ResponseWriter, r *http.Request) {
//}
//
//// Ищем ивент
//t, err := h.dal.Template.GetByNameAndUserID(r.Context(), resp.EventName, user.UserID)
//t, err := h.dal.Template.GetByNameAndUserID(r.Context(), resp.EventName, amoData.UserID)
//
//if err != nil {
// h.reportError(w, err, http.StatusInternalServerError)
@ -227,7 +310,7 @@ func (h *Handlers) TemplateInit(w http.ResponseWriter, r *http.Request) {
// return
//}
//
//YaDiskData, err := h.dal.YaDisk.GetByUserID(r.Context(), user.UserID)
//YaDiskData, err := h.dal.YaDisk.GetListByUserID(r.Context(), amoData.UserID)
//if err != nil {
// h.reportError(w, err, http.StatusInternalServerError)
// return

251
handlers/templateGroup.go Normal file

@ -0,0 +1,251 @@
package handlers
import (
"errors"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
"github.com/gorilla/mux"
"net/http"
)
type ReqTemplateGroupCreate struct {
Name string `json:"name"`
}
type RespTemplateGroupCreate struct {
ID string `json:"id"`
}
func (h *Handlers) TemplateGroupCreate(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateGroupCreate
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.Name == "" {
h.reportError(w, errors.New("name required"), http.StatusBadRequest)
return
}
groupID, err := h.dal.TemplateGroup.Insert(r.Context(), &model.TemplateGroup{
UserID: amoData.UserID,
Name: req.Name,
})
sendResponse(w, http.StatusOK, &RespTemplateGroupCreate{ID: groupID})
}
func (h *Handlers) TemplateGroupGet(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
if id == "" {
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
return
}
resp, err := h.dal.TemplateGroup.GetByID(r.Context(), id)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
sendResponse(w, http.StatusOK, &resp)
}
func (h *Handlers) TemplateGroupGetList(w http.ResponseWriter, r *http.Request) {
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
resp, err := h.dal.TemplateGroup.GetListByUserID(r.Context(), amoData.UserID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
sendResponse(w, http.StatusOK, &resp)
}
type ReqTemplateGroupEdit struct {
ID string `json:"id"`
Name string `json:"name"`
}
func (h *Handlers) TemplateGroupEdit(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateGroupEdit
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.ID == "" {
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
return
}
if req.Name == "" {
h.reportError(w, errors.New("name required"), http.StatusBadRequest)
return
}
err = h.dal.TemplateGroup.Update(r.Context(), &model.TemplateGroup{
ID: req.ID,
UserID: amoData.UserID,
Name: req.Name,
})
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
type ReqTemplateGroupDelete struct {
ID string `json:"id"`
}
func (h *Handlers) TemplateGroupDelete(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateGroupDelete
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.ID == "" {
h.reportError(w, errors.New("group_id required"), http.StatusBadRequest)
return
}
//TODO: Крайне желательно переписать на транзакции!
err = h.dal.Template.DeleteGroupFromAll(r.Context(), req.ID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
err = h.dal.TemplateGroup.Delete(r.Context(), req.ID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
type ReqTemplateGroupPut struct {
GroupID string `json:"group_id"`
TemplateID string `json:"template_id"`
}
func (h *Handlers) TemplateGroupPut(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateGroupPut
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.TemplateID == "" {
h.reportError(w, errors.New("template_id required"), http.StatusBadRequest)
return
}
if req.GroupID == "" {
h.reportError(w, errors.New("group_id required"), http.StatusBadRequest)
return
}
err = h.dal.Template.PushGroup(r.Context(), req.TemplateID, req.GroupID, amoData.UserID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
type ReqTemplateGroupRemove struct {
GroupID string `json:"group_id"`
TemplateID string `json:"template_id"`
}
func (h *Handlers) TemplateGroupRemove(w http.ResponseWriter, r *http.Request) {
var req ReqTemplateGroupRemove
amoData := getAmoByJwt(r)
if amoData == nil {
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
return
}
err := decodePost(&req, r)
if err != nil {
h.reportError(w, err, http.StatusBadRequest)
return
}
if req.TemplateID == "" {
h.reportError(w, errors.New("template_id required"), http.StatusBadRequest)
return
}
if req.GroupID == "" {
h.reportError(w, errors.New("group_id required"), http.StatusBadRequest)
return
}
err = h.dal.Template.PullGroup(r.Context(), req.TemplateID, req.GroupID, amoData.UserID)
if err != nil {
h.reportError(w, err, http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}

28
main.go

@ -97,11 +97,8 @@ func main() {
r.HandleFunc("/amo/state", func(w http.ResponseWriter, r *http.Request) {
h.AmoState(w, r, opts.AmoRedirectUrn)
})
r.HandleFunc("/amo/webhook", h.AmoWebhook)
r.HandleFunc("/amo/gdisk/getTemplateDir", h.GDiskGetDirTemplate)
r.HandleFunc("/amo/getTemplate", h.AmoGetTemplate)
r.HandleFunc("/amo/setTemplate", h.AmoSetTemplate)
r.HandleFunc("/amo/generateDoc", h.AmoGenerateDoc)
r.HandleFunc("/amo/webhook", h.GeneratorByAmoWebhook)
r.HandleFunc("/amo/generateDoc", h.GeneratorByAmoLead)
r.HandleFunc("/amo/access_rules", h.AmoAccessRules)
// Set rules for Amo end-points
@ -118,6 +115,7 @@ func main() {
r.HandleFunc("/yadisk/resources/put", h.YaDiskPutResources)
r.HandleFunc("/yadisk/resources/delete", h.YaDiskDeleteResources)
r.HandleFunc("/gdisk/getTemplateDir", h.GDiskGetDirTemplate) // устарело?
r.HandleFunc("/gdisk", h.GDiskSaveToken)
r.HandleFunc("/gdisk/setSettings", h.GDiskSetSettings)
r.HandleFunc("/gdisk/getList", h.GDiskGetList)
@ -126,13 +124,27 @@ func main() {
r.HandleFunc("/gdisk/resources/put", h.GDiskPutResources)
r.HandleFunc("/gdisk/resources/delete", h.GDiskDeleteResources)
r.HandleFunc("/template/new", h.TemplateNew)
r.HandleFunc("/template/getById", h.TemplateGetByID)
r.HandleFunc("/template/set", h.TemplateSet)
r.HandleFunc("/template/get", h.TemplateGet)
r.HandleFunc("/template/getListByUser", h.TemplateGetListByUser)
r.HandleFunc("/template/getListByGroup", h.TemplateGetListByGroup)
r.HandleFunc("/template/update", h.TemplateUpdate)
r.HandleFunc("/template/delete", h.TemplateDelete)
r.HandleFunc("/template/init", h.TemplateInit)
r.HandleFunc("/group/create", h.TemplateGroupCreate)
r.HandleFunc("/group/getList", h.TemplateGroupGetList)
r.HandleFunc("/group/edit", h.TemplateGroupEdit)
r.HandleFunc("/group/put", h.TemplateGroupPut)
r.HandleFunc("/group/remove", h.TemplateGroupRemove)
r.HandleFunc("/group/delete", h.TemplateGroupDelete)
r.HandleFunc("/group/{id}", h.TemplateGroupGet)
r.HandleFunc("/generator/byAmoLead", h.GeneratorByAmoLead)
r.HandleFunc("/generator/byData", h.GeneratorByData)
r.HandleFunc("/generator/byTemplate", h.GeneratorByData)
r.HandleFunc("/generator/byAmoWebhook", h.GeneratorByAmoWebhook)
//#endregion
// Middlewares
@ -143,7 +155,7 @@ func main() {
mw.MiddlewareCors,
// mw.MiddlewareJwt, TODO: Переделать под Пеновский сервис авторизации
mw.MiddlewareAmoJwt,
//mw.MiddlewareAmoPlug,
mw.MiddlewareAmoPlug,
mw.Logger,
)

@ -263,19 +263,29 @@ func (mw *Middleware) MiddlewareAmoJwt(next http.Handler) http.Handler {
func (mw *Middleware) MiddlewareAmoPlug(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, err := mw.dal.Amo.GetByID(r.Context(), "63226edec2259da3375fe2a4")
if err != nil {
mw.reportError(w, err, http.StatusInternalServerError)
if strings.Contains(r.URL.String(), "/assets/") {
next.ServeHTTP(w, r)
return
}
if data == nil {
mw.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
ctx := r.Context()
if r.Header.Get("TestAuth") == "75bc853ae763ffc36cad97069682fed1" {
data, err := mw.dal.Amo.GetByID(r.Context(), "63226edec2259da3375fe2a4")
if err != nil {
mw.reportError(w, err, http.StatusInternalServerError)
return
}
if data == nil {
mw.reportError(w, errors.New("amo account not found"), http.StatusUnauthorized)
return
}
ctx = context.WithValue(ctx, "amoData", data)
}
ctx := context.WithValue(r.Context(), "amoData", data)
next.ServeHTTP(w, r.WithContext(ctx))
})
}

@ -1,32 +1,32 @@
-----BEGIN CERTIFICATE-----
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
LiASDdNrOPfTm8Zu86YRPQ==
Lm9yZzCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2ALc++yTfnE26dfI5xbpY9Gxd
/ELPep81xJ4dCYEl7bSZAAABhGJrxCEAAAQDAEcwRQIhALvhrXlgLVUrOdDJ+v+0
1bITSoGGnx1AtE/qVsMdjZxKAiBmKFihL9ugHjH6Wp3HBOjQg97w1qf+tplKSOE8
fV0BuwB2AHoyjFTYty22IOo44FIe6YQWcDIThU070ivBOlejUutSAAABhGJrxEAA
AAQDAEcwRQIgIVOVnfb5oqoAcdmGhBMU/d65vfUvt2QP8yU1pmu0uS0CIQD++4kE
/DEYXBye634QVjmf/IcoXsPHQyQ3jIAmInteZDANBgkqhkiG9w0BAQsFAAOCAQEA
a9vkSsknNH5mH8QoFukQPIXDzYAHCaUpL7CzlHt1OWwTIIX/r8J91jrST9k/NHoh
rmvRWwlaLH0i5usYRKotSzdNETaJ5SUSMHdLv8Y/yAMGwURaDQeVwdsMsmraiUxX
84i86N1L/NSgWbgm2g7XS8TSA3mIyBF0BgLDl5pp7Tjywxj538+8a4fnHdFSobrd
3E52YQFP2mzzwgXenJebXrdaYDTAjjMDBpySC6vnRAubLedJE6Tfo2vkrwxfFTJY
ECRPtsEZQj4gyXb+PoPAYVH4DheiIN+xnAS0ZUEVYto4NfszU6dt9D31I3ZBD9a/
Xpf0e6rBigJ5FrkAlPU8rg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw

@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJfpjMA62YtEpv
FySV4ZiNLn5nsNTFTKmtGpQOvrHVZc2TTjLzGKXry2IONhJ25DUpi7SW/SFxq4oe
6uGtWm5c6tQj3KwQjLH/HADlxXqf3qBky/1w7ovgPZX83P/yf5o4ll+L0sdrEdtc
rhNG43S6pQJGGnNXNIgfPlJhqbB6WvxSjDOMIi5sJPm1Mvm3eDgoX0aRi9jXylxQ
UdaTo7U3gKq8TIVZVGM7EQ300q0TN9Jyi/h0/9fl1T0eDK6V3Y4+/pJEBr87GFhs
7THBwNX4BFFQYld9/CEDS+fk1OKZFvj1xTHc8C34s/iyrd53+60k9LM74HPCCUH+
goDPCbm5AgMBAAECggEBAJwmA3t3Djzc2yIkKTIN1g7zDPqGSx1rP8LqafrTRTU+
44VYgJtraonE34Rr2vtP9vLvVU/9csGIUk2LcMDK5+QSB7yS8rUQk5BDv15RH6ps
+Jekjg/KjZOFpoqDKcZfpMBdqEXPXsNW30x/imjRNFDAN3bkYKYgC61KusT8n8rw
/dEhz2Q7oRBzjkFlK97CvTQTxGR47bZnaQsNPdXorkauJps9eAWXDn569nXWGJKy
nalXpeB8dJdgy4jyCSmZ8AIo2MxoDZ6OQHKMxBdadhZeXz+TJ1qc5vvvosIlXDWm
yIfwkABcOJ+u64OIDFY2u1w+xXKwScUobAdAvT4bagECgYEA/CBH/ca4ZcYkKoty
mRtjwtL/bGb06xOSpPAGlGu8s/uwdYTYUUmNnlIOF457nlQX03yhh0hhpZpCGHuO
PVkjQsgk8WhxusWU90hlZjQ/lMlnqCPKZHDoKsskoQBFH+fv8g/LfKI4RaV6YuIe
0fsQ5V7RqUuscaoONYnVim8LMJECgYEAzJcpAi+Shm9rvHKe5tSAOce60mcW/QMy
5nufWcUnuYUPgsYUzKJR/TIIKNyhD6E1U2Z5mRMfAfJuNhtMVBrHbrUWLkognE7S
j8Yf7RT7eIsdL95KnMnBRLTsoaymrFEf8GIwglr6EzXudvlo4d+tLUF1ZJ7mdj22
nK2MqPUxCqkCgYBVjiK/1BI4vv8AzOcrW2cD8pOoVluf9blabPTeopybOrpLdrPt
CZeb9N5BUiFSvdiD9JPfk0lHZ8wsAKlo2fmkLMSUgsutBGUjcJawEuTMeXfKT7Lb
WJEADIU2eR/7zrnWm1OCzI1p3Nhl+7NXr+mw2/crirlOrNU7h7VFz56tcQKBgQCh
ME8c68IzrMFjHaNYFgBYhaYJczNHcCfAM5HetliP7+fCjrGAcDrMk4ieOQWkPMy4
wrn3AnuhmxF+C4/di6Oo839gRQLgY7G9mMk6jxd5Z5E9T5PVZ5efvDPbRR2kEd5q
E9JIQclZLVqN3f7mRsY4K6SD/DVy3zhqxMlXrKZQ0QKBgQC0TQKnqlRDwQoatEqA
xp08FfK80blfRjkG3CvRLin/SxJMk2Vgb2P6pLmWJYe0le7NKGH86APJy9L2yDr+
L6YWGYK2P1gTUPwf7YNhDM5Y//ozZM7cGHn32jWX8hhNPU7RXzbsk/c/CVyBH0jt
CzVV6EzOmItREJw+VHxmrNXR1Q==
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLd4BTvNDyInOU
eqbE8qi218shc0EoHFbcHrHq1Hm/6kFkVYXpJPehwgHJh9C0YB412dir3n8NFWdL
JidVx7juUjc9UH5fbmIZQhBbFZxs0/kSnh+5rIDbP0+1N8Xotds/zzfEUAP0ypDO
v7vsmNSub66ndFmY9rwX6jjeaxm4UF5CANv1TpmJGXfKqHrtQHk89UzkNbXzC8W+
DU1FYOYA3sVCCLoCTJJ0smOjT/iId9Xx7qEOEjWrRNye+ynxUXDlAmdFhxB8qFhV
d7rYeNEOzTzCEqWm1NyqK/NfPYDGdT3J+NWx1ocIFQ7KGkZ0dC6IiOymJNp00mYc
4eApkYYFAgMBAAECggEAdst26W08saLbyL0z0Zm8V8T2nLkmOb0SGcLyLiGQVDT5
qRMl9FHZI2CamofpmubjvJ1MnExz8belb4L/RF4v4zWteuccYauZKxYfZo7fncrF
idE4xLerJFd6ulut+Yj0UfUyojP1m18J3SylFCbHRnF+j9am2WB1waDHQ1VU1v9K
W0Ny0Y3iBPQt34p6+Zt1Fi2zRfW3Wngld8o7Z09uyh5zsu8Esk7iQpSoV5XD0WRv
Ss13WrOZ33VwZxjYAsRh0koz96l4jpmCS5khnzSKmf3uaEOilrUPuGO6VMDv/yVF
guPvHWfusfT57hl6hWhLWb4bT3ZpOLiasyGKIo8lAQKBgQD1CtzQI8Ri+Hpga9XG
5kzO19sggWYxBcVi3Z+IUw9JOV80rMQUJEoFiahyvpItAyFTOcjxYaBHi0zHK5ZK
hRXoc7nvbkha4eVfg3BeSyh+8xjTB754YNfImByso+rW9W+D3n6feFcN4nB3i9qm
vdgCw3ws5XvJjKlFFfUs6sI7/QKBgQDUkLMExgccllxGmzHL7K68oqKKPZsIANBs
FUIFDoGimlfrPdja8/viEDDi15ZhH3tv1LJUeC/aMaLgU2EGarRbYpdD9vKZLvPi
ydEboGFUNJbdnfKxTHeaUrE35xUv8b499bDKsCohW1r4hvadT+8uDr23JtL4SsqH
+ug4+L1cqQKBgQDU9FLAREU46c6Ymz6W87BOlkMmNa6U7foDmK07MUv4i/aUdYyW
II9/zolo5vtsSOseQ/rA4+ICKypXcSbUrmJCuMgfL42MBgNsBXOTTufro+KwC2vZ
e/grqR5KXs4JcBUw2hzbBB9Lvr2U9yLXg+cFR9RTxD/XAfpdQt7m4UJaFQKBgQDI
44vceg6kjNHehLN2J1QowIdeoMRQtvxC+YAwaTpI4xcuIoA8xZMKXgTljZv4ZBlz
Yg+7Vu7ahkiJOyOaPeP/7dhJiixSaxZhAhzWwCbbvuvJvIlt2He8aGRGEeVrL0t9
ISKZHA5lAgKimGKf37iKzbGsU0vVDlIEWzN3DFViKQKBgHTpq5SeBp3NSnQw5a0y
6vPYtm0t/jysOy3UGIl7qf/P5Ob994E7gVluPN8r4wXcmYqw9/glT2pdqfoBeQmX
UZ0zvcbdTERoNbQP8xkoN6C/8kUxbCVY3TsvteZQbJ7XB1Lcvf5k3aVWYDKabEzX
6kat3P/xhuX2aBJ25n+DEmwt
-----END PRIVATE KEY-----

@ -1,32 +1,32 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw

@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCPHrr9tFOzGHB
km7dc//5jYY7tzWYwtTZpfV5wjB3ZPT2ubl1p0CbLa281Zr18+X0jRoC7raCaZ/D
hmwD3lCbCFGRc/AvFR1ZwACTU+Q/D+/1eE8gi+i7xCWliaswu/LBtblLSL64O+IR
+RUhdw9vwUFe7G5j+uODaAGKg1cy/Zs87Y/LSAxWiia6+ko8ioSrJ1/hdtFmaNOZ
MxAgcCjLohoABWqm9dUdkJlhb4LM0yJ2vxDnBh9o+ER2OOKawyqFREBJ3TGHR5SA
kJ5I4R+CC5s6clG6S8OmEzqsCXsyAAg7+xcVtSUZPOrQRy7cGSgUKhbX6cedI35G
sSldowwjAgMBAAECggEAN7vM9apD0t14a2fOIgMn/v5p9vaSDXxSQQWK014yNAAm
/ii6m5TbR+uqf5W3Oj26zRozzYWbnv4Z1qvakJ2Y+XNAnIDs+UWQv3EFeUDILIQx
MXlNEySyKjaVKtO+6GP1uzmeqoh8GTctnkSfmJOmPUXxsQAciNmzsMAGOS2Ittto
Tt0Cn4das3PstOhmDBDAFQP6O4vWZ4TZi5xTgeEzc8kx4FgVDqAlJOty9qzUNzha
NWjAqkQX5Xn/4jdKUwe/BIrVQ8f5PJ7pk38lARkbBaffNs9VEvIc4lPstM9+i4jD
gptbcRt2T47B4d1lalqX5Nk4WVeruoo1XanOZ3oPUQKBgQDke+t9esRtc8VAaVG6
mnQEXlKgNQqvOxhKWcltiJ3CiiYSM+uBnp893fjAQmk6sX/y4Asqv5tRSwVykwMO
+2PwTkDe5v/6KKpxkXq+Ya7ymuQWavd1w08Hj/Z/pQ/gPZHkpKwjc1ymCfjizDpL
ZKbsBKj5duMNqli29j0WJgL2KwKBgQDZoLZ4Pot1dn5FbKp+qh9gBqO5NrFYPJ0f
zj8GCUCw0QroXsXGJTke9aMYKcSxnCQM6ykp8s4A+AlfU+1GAvd3JQE0dB9nhpSq
jwT8uCkDDwCSl3CRr7D6e/TpMaL983kcXvNjJhj09wvsq/DM3yqm5/gwQM2XBvRT
9MBPJzp96QKBgQDIyBjV6Kdqo3yoMKTwfUAMgrLLNDFScXTUCXjXt2EjDnGMN3Hy
Muku3bv1f6anPEn6rWVCyKP9WRbNa2EZrlJRXwLknkw9kbTOHhCl8oNhkDl1dcRG
CT6On7T20J9V5+Un7omSkZLOGh9LdjqX/DgvWZz/s7itTo+tIE/oAblChwKBgA3k
zMFwfMbLAdS800Wy5r3irqEsdLYFaKKXMD7aaF7heajMJCQ6TCNF21u3ju8n4MVS
XhZnge9d5ntHiGZn2hSpMCKBJ2Acn3EkIFViDHw9gPPa5zzl0o6rSz94A8fiu2Cs
Ty2NSRqaixBZCc6KkNaHCLlL6dQyhXa2sXBcOMfBAoGACHzkx9XvFdticGjYYvr8
yZHWOLzJQOF1Qlys89TUTJ2BHILReKzVYv9J/XTkQTKZGgt/SsMlEdVBtt50N8UE
sqdH2kEjgKLkwbzBBIENgGKpAfYI/Uq4vDLGeZx6TsKGVdknvy/DPn7jh4IRwjyo
RT6t39pnS2hkQxnHtwr0iog=
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDjSS+IXA6cwbtx
YA9Iascbaplg63jG2ysUn1ZCN8GZG4E+54zqArN+sS2twGmO3+wxUPYsbfvetTOq
umGMV8Zr8QJGXIlq4l3jTlmALRRpCC/MyHj3AKw30ddrcwyUtQqOuSkPfEjetJv9
ZPrt6GXzIIb488Dru9+1TKRW0BNX+a7DkgiDEt4z1WoB7bGQpIezbrB5WJOF/19z
YypyCDLbsOMBUh01bcLnhQz2smozLiezlaazbcZQ8XFBksOvMQCbVp2HnF56PDrt
bPjrA766oNd0EtR+eL5xpzdzu1LV4jhTVhtKUOIY2HcweMFj77jMicnsW2HLv4Vi
8o07vHRzAgMBAAECggEBAIM5Z/YkoFMlD2HgAjLfY2GS5Ecu7KZzN6ZKcHT+2Anb
9X0qFxOsx5FoHmVo6AkTg7zdb6QrQ/ZLTC9QOK3cp7T+iz+wga5yT57DR61XWadi
kKZ9QEnr24LG5sckv6jD9fp9MRW9vhzGziE4wh/Fw8bhiswFf+caq4hzXZa5v9FU
QlNierJCf+wVzMMmGSPwvWJ/brcpRyv7Gs8jcDRLOUZuj8odQ/tzV5z6Y+txbROF
YQDIsULLkyfLzo3pbXD9Ga7Dh5SQDpDvu21jYQI2j7yUVMEyG4ONOmMH05TI5x/Z
H/Ol8POqguvwOQ2swthdg1gagzjAiRF9iyPb/u9+LVECgYEA9u60I1mZiu91rMAA
sOT3DmOMOzfvTok7nuWDl1ZuW2OzDKUisy8FehcIhm5HLadpKBVa5PbNGcRf5LrM
5itttw0byppIEdyzGkx2MTQKi1/kCUQT60cjTSbT7KYEGL4hrsLYPW9L5MihIpI0
I9a4tVX51kPg3O8DzZW9iZJEo+UCgYEA66HLP5ZP6wR3mlcVQalZ3jvyhmw88D7S
rAMNp0V4izw89a4+7xnpH3lRO4sMZEEPS7QxaAOGv40oTK/2aB0cNgDwxyd2Z3th
ZZqnJTSrU/GcoeAdPlgkbq3RxcXFAKItJDkGjnTEPOhh1uKrnNqZL4KllFkeZg0X
GsYpwDYo4XcCgYBXpq2cqq5c6dkMY+8a23tyyRU65AT3DLF0GqYWLyDnIcGpqGhj
0DoSd2CYT0bGxtkF2Ga2RYDSN6mOSFx5C0tbobSOuyr/5CZTHHcLyhxAEt6gB2FG
r66xMSoio19q5PqRzSnyzLHU2P6RhfIqEoroG0eereOAqPrhm9h2n8vrnQKBgDen
PDElmHSi1njuroeWrzItKIgVUoNP40RbaEMkxmbkcGV6pUSl8wjLB6OvoNqg/zLb
OXwesRnXBjiuqt1GWt5qdHQlXvLsEkIEOAwyl3C5NUyKeX27Jce6aDx1DKWsqErQ
6TqGW78jB9DQMsZWXy34hpE2R1bFKrrZKQ1L/XXbAoGAEFOIy87fY8G8oCwis9g7
PjxeaK1Q+Cz8WpOydAwXI2syTnoqGizHX3JexVDnFMIebg/76ib7TEzNOJCyjmM3
LN0RCOG9qA91S9/GzwEl4ABs6HCOELZbwIJMnUOoM9sejwIlu0KFGKoURJt8CDVP
POpKTvY6wV23WwXZid44TBQ=
-----END PRIVATE KEY-----

@ -1,16 +1,15 @@
package templategen
import (
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/gdisk"
)
func GDiskGenerateDoc(template *model.Template, saveFolderID string, client *GDisk.Client, data interface{}) error {
filename := GenerateDocName(template.Name, template.UserID)
func GDiskGenerateDoc(file, name, userID, saveFolderID string, client *GDisk.Client, data interface{}) error {
filename := GenerateDocName(name)
// Download file
downloaded := TempDownloaded + "/" + filename
err := client.DownloadFile(downloaded, template.FileID)
err := client.DownloadFile(downloaded, file)
if err != nil {
return err
}

@ -1,16 +1,15 @@
package templategen
import (
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
"github.com/Pena-Co-Ltd/amocrm_templategen_back/yadisk"
)
func YaDiskGenerateDoc(template *model.Template, saveFolder string, client *YaDisk.Client, data interface{}) error {
filename := GenerateDocName(template.Name, template.UserID)
func YaDiskGenerateDoc(file, name, userID, saveFolder string, client *YaDisk.Client, data interface{}) error {
filename := GenerateDocName(name)
// Download file
downloaded := TempDownloaded + "/" + filename
err := client.DownloadResource(template.Filename, downloaded)
err := client.DownloadResource(file, downloaded)
if err != nil {
return err
}