Compare commits

...

12 Commits

14 changed files with 4661 additions and 2335 deletions

View File

@ -1,88 +0,0 @@
{
"meta": {
"source": "Таблица основных типов ISO-контейнеров (внешние/внутренние размеры, дверной проём, масса, объём)",
"usage": "Сверка п.21 FCL (проходимость груза в дверной проём 20DV, 40DV, 40HC) и оценка payload/объёма."
},
"types": {
"20DV": {
"label": "20' Standard (Dry Cube) — соответствует 20DV в критериях",
"external_mm": { "length": 6058, "width": 2438, "height": 2591 },
"internal_mm": { "length": 5905, "width": 2350, "height": 2381 },
"door_opening_mm": { "width": 2336, "height": 2291 },
"max_gross_kg": 30480,
"tare_kg": 2370,
"payload_kg": 28110,
"volume_m3": 33.2
},
"20HC": {
"label": "20' High Cube",
"external_mm": { "length": 6058, "width": 2438, "height": 2896 },
"internal_mm": { "length": 5905, "width": 2350, "height": 2693 },
"door_opening_mm": { "width": 2340, "height": 2597 },
"max_gross_kg": 30480,
"tare_kg": 2340,
"payload_kg": 28140,
"volume_m3": 37.5
},
"20HC_PW": {
"label": "20' High Cube Pallet Wide",
"external_mm": { "length": 6058, "width": 2484, "height": 2896 },
"internal_mm": { "length": 5898, "width": 2426, "height": 2698 },
"door_opening_mm": { "width": 2374, "height": 2585 },
"max_gross_kg": 30480,
"tare_kg": 2580,
"payload_kg": 27900,
"volume_m3": 38.6
},
"40DV": {
"label": "40' Standard (Dry Van) — соответствует 40DV в критериях",
"external_mm": { "length": 12192, "width": 2438, "height": 2591 },
"internal_mm": { "length": 12039, "width": 2350, "height": 2372 },
"door_opening_mm": { "width": 2336, "height": 2291 },
"max_gross_kg": 30480,
"tare_kg": 4000,
"payload_kg": 26480,
"volume_m3": 67.8
},
"40HC": {
"label": "40' High Cube — соответствует 40HC в критериях",
"external_mm": { "length": 12192, "width": 2438, "height": 2896 },
"internal_mm": { "length": 12039, "width": 2350, "height": 2693 },
"door_opening_mm": { "width": 2340, "height": 2597 },
"max_gross_kg": 32500,
"tare_kg": 4200,
"payload_kg": 28300,
"volume_m3": 76.5
},
"40HC_PW": {
"label": "40' High Cube Pallet Wide",
"external_mm": { "length": 12192, "width": 2500, "height": 2896 },
"internal_mm": { "length": 12039, "width": 2432, "height": 2693 },
"door_opening_mm": { "width": 2432, "height": 2597 },
"max_gross_kg": 35000,
"tare_kg": 4400,
"payload_kg": 30600,
"volume_m3": 79.3
},
"45HC_PW_A": {
"label": "45' High Cube Pallet Wide (Type A)",
"external_mm": { "length": 13716, "width": 2500, "height": 2750 },
"internal_mm": { "length": 13513, "width": 2444, "height": 2549 },
"door_opening_mm": { "width": 2416, "height": 2439 },
"max_gross_kg": 34000,
"tare_kg": 4180,
"payload_kg": 29820,
"volume_m3": 85.1
},
"45HC_PW_B": {
"label": "45' High Cube Pallet Wide (Type B)",
"external_mm": { "length": 13716, "width": 2500, "height": 2896 },
"internal_mm": { "length": 13513, "width": 2444, "height": 2670 },
"door_opening_mm": { "width": 2416, "height": 2580 },
"max_gross_kg": 34000,
"tare_kg": 5080,
"payload_kg": 28920,
"volume_m3": 89.5
}
}
}

View File

@ -416,7 +416,7 @@
"label": "Страна, город, адрес забора" "label": "Страна, город, адрес забора"
}, },
"right": { "right": {
"num": "19", "num": "18",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ" "label": "Страна, город, точный адрес доставки, Место ТО в РФ"
} }
}, },
@ -483,17 +483,17 @@
{ {
"type": "pair", "type": "pair",
"left": { "left": {
"num": "18", "num": "19",
"label": "Место таможенного оформления при экспорте из РФ" "label": "Место таможенного оформления при экспорте из РФ"
}, },
"right": { "right": {
"num": "19", "num": "20",
"label": "Наличие Фумигации на деревянной таре при экспорте из РФ" "label": "Наличие Фумигации на деревянной таре при экспорте из РФ"
} }
}, },
{ {
"type": "left_12", "type": "left_12",
"num": "20", "num": "21",
"label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC" "label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC"
} }
] ]
@ -508,7 +508,7 @@
"label": "Страна, город, адрес забора" "label": "Страна, город, адрес забора"
}, },
"right": { "right": {
"num": "19", "num": "18",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ" "label": "Страна, город, точный адрес доставки, Место ТО в РФ"
} }
}, },
@ -575,17 +575,17 @@
{ {
"type": "pair", "type": "pair",
"left": { "left": {
"num": "18", "num": "19",
"label": "Место таможенного оформления при экспорте из РФ" "label": "Место таможенного оформления при экспорте из РФ"
}, },
"right": { "right": {
"num": "19", "num": "20",
"label": "Наличие Фумигации на деревянной таре при экспорте из РФ" "label": "Наличие Фумигации на деревянной таре при экспорте из РФ"
} }
}, },
{ {
"type": "left_12", "type": "left_12",
"num": "20", "num": "21",
"label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC" "label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC"
} }
] ]
@ -600,7 +600,7 @@
"label": "Страна, город, адрес забора" "label": "Страна, город, адрес забора"
}, },
"right": { "right": {
"num": "19", "num": "18",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ" "label": "Страна, город, точный адрес доставки, Место ТО в РФ"
} }
}, },
@ -667,17 +667,17 @@
{ {
"type": "pair", "type": "pair",
"left": { "left": {
"num": "18", "num": "19",
"label": "Место таможенного оформления при экспорте из РФ" "label": "Место таможенного оформления при экспорте из РФ"
}, },
"right": { "right": {
"num": "19", "num": "20",
"label": "Наличие Фумигации на деревянной таре при экспорте из РФ" "label": "Наличие Фумигации на деревянной таре при экспорте из РФ"
} }
}, },
{ {
"type": "left_12", "type": "left_12",
"num": "20", "num": "21",
"label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC" "label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC"
} }
] ]
@ -692,7 +692,7 @@
"label": "Страна, город, адрес забора" "label": "Страна, город, адрес забора"
}, },
"right": { "right": {
"num": "19", "num": "21",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ" "label": "Страна, город, точный адрес доставки, Место ТО в РФ"
} }
}, },

View File

@ -0,0 +1,801 @@
{
"version": 1,
"source_xlsx": "Запрос для ИИ Общий(3).xlsx",
"by_shipping_type": {
"Автомобильная перевозка (LTL)": {
"sheet": "Авто LTL интерфейс",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "19",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество грузовых мест и вес, объем"
},
"right": {
"num": "7",
"label": "Габариты грузовых мест ДхШхВ"
}
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Штабелирвоание с другими отправками"
},
"right": {
"num": "11",
"label": "Штабелирвоание между собой"
}
},
{
"type": "pair",
"left": {
"num": "9",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "13",
"label": "MSDS"
},
"right": {
"num": "14",
"label": "DGM"
}
},
{
"type": "pair",
"left": {
"num": "15",
"label": "Название бренда"
},
"right": {
"num": "16",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "17",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "18",
"label": "Требуется ли замена документов"
}
}
]
},
"Автомобильная перевозка (FTL)": {
"sheet": "Авто FTL интерфейс",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "19",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество и типоразмер машин"
},
"right": {
"num": "7",
"label": "Количество грузовых мест и вес, объем"
}
},
{
"type": "left_12",
"num": "8",
"label": "Габариты грузовых мест ДхШхВ"
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "11",
"label": "MSDS"
},
"right": {
"num": "13",
"label": "DGM"
}
},
{
"type": "pair",
"left": {
"num": "14",
"label": "Название бренда"
},
"right": {
"num": "15",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "16",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "17",
"label": "Требуется ли замена документов"
}
}
]
},
"Морская перевозка (LCL)": {
"sheet": "Море, море+жд, жд LCL интерфейc",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "19",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество и типоразмер машин"
},
"right": {
"num": "7",
"label": "Количество грузовых мест и вес, объем"
}
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Штабелирвоание с другими отправками"
},
"right": {
"num": "11",
"label": "Штабелирвоание между собой"
}
},
{
"type": "pair",
"left": {
"num": "9",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "13",
"label": "MSDS"
},
"right": {
"num": "14",
"label": "DGM"
}
},
{
"type": "pair",
"left": {
"num": "15",
"label": "Название бренда"
},
"right": {
"num": "16",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "17",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "18",
"label": "Требуется ли замена документов"
}
}
]
},
"Железнодорожная перевозка (LCL)": {
"sheet": "Море, море+жд, жд LCL интерфейc",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "19",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество и типоразмер машин"
},
"right": {
"num": "7",
"label": "Количество грузовых мест и вес, объем"
}
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Штабелирвоание с другими отправками"
},
"right": {
"num": "11",
"label": "Штабелирвоание между собой"
}
},
{
"type": "pair",
"left": {
"num": "9",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "13",
"label": "MSDS"
},
"right": {
"num": "14",
"label": "DGM"
}
},
{
"type": "pair",
"left": {
"num": "15",
"label": "Название бренда"
},
"right": {
"num": "16",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "17",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "18",
"label": "Требуется ли замена документов"
}
}
]
},
"Мультимодальная перевозка море + ж/д (LCL)": {
"sheet": "Море, море+жд, жд LCL интерфейc",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "19",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество и типоразмер машин"
},
"right": {
"num": "7",
"label": "Количество грузовых мест и вес, объем"
}
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Штабелирвоание с другими отправками"
},
"right": {
"num": "11",
"label": "Штабелирвоание между собой"
}
},
{
"type": "pair",
"left": {
"num": "9",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "13",
"label": "MSDS"
},
"right": {
"num": "14",
"label": "DGM"
}
},
{
"type": "pair",
"left": {
"num": "15",
"label": "Название бренда"
},
"right": {
"num": "16",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "17",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "18",
"label": "Требуется ли замена документов"
}
}
]
},
"Морская перевозка (FCL)": {
"sheet": "Море, море+жд, жд FCL интерфейc",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "18",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество и типоразмер контейнеров"
},
"right": {
"num": "7",
"label": "Количество грузовых мест и вес, объем"
}
},
{
"type": "left_12",
"num": "8",
"label": "Габариты грузовых мест ДхШхВ"
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "11",
"label": "MSDS"
},
"right": {
"num": "13",
"label": "Technical Description of Goods in Railway Transport"
}
},
{
"type": "pair",
"left": {
"num": "14",
"label": "Название бренда"
},
"right": {
"num": "15",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "16",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "17",
"label": "Требуется ли замена документов"
}
},
{
"type": "pair",
"left": {
"num": "19",
"label": "Место таможенного оформления при экспорте из РФ"
},
"right": {
"num": "20",
"label": "Наличие Фумигации на деревянной таре при экспорте из РФ"
}
},
{
"type": "left_12",
"num": "21",
"label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC"
}
]
},
"Железнодорожная перевозка (FCL)": {
"sheet": "Море, море+жд, жд FCL интерфейc",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "18",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество и типоразмер контейнеров"
},
"right": {
"num": "7",
"label": "Количество грузовых мест и вес, объем"
}
},
{
"type": "left_12",
"num": "8",
"label": "Габариты грузовых мест ДхШхВ"
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "11",
"label": "MSDS"
},
"right": {
"num": "13",
"label": "Technical Description of Goods in Railway Transport"
}
},
{
"type": "pair",
"left": {
"num": "14",
"label": "Название бренда"
},
"right": {
"num": "15",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "16",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "17",
"label": "Требуется ли замена документов"
}
},
{
"type": "pair",
"left": {
"num": "18",
"label": "Место таможенного оформления при экспорте из РФ"
},
"right": {
"num": "19",
"label": "Наличие Фумигации на деревянной таре при экспорте из РФ"
}
},
{
"type": "left_12",
"num": "20",
"label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC"
}
]
},
"Мультимодальная перевозка море + ж/д (FCL)": {
"sheet": "Море, море+жд, жд FCL интерфейc",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "19",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество и типоразмер контейнеров"
},
"right": {
"num": "7",
"label": "Количество грузовых мест и вес, объем"
}
},
{
"type": "left_12",
"num": "8",
"label": "Габариты грузовых мест ДхШхВ"
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "12",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "11",
"label": "MSDS"
},
"right": {
"num": "13",
"label": "Technical Description of Goods in Railway Transport"
}
},
{
"type": "pair",
"left": {
"num": "14",
"label": "Название бренда"
},
"right": {
"num": "15",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "16",
"label": "Требуется ли дополнительный сервис - фитоконтроль, иное"
},
"right": {
"num": "17",
"label": "Требуется ли замена документов"
}
},
{
"type": "pair",
"left": {
"num": "18",
"label": "Место таможенного оформления при экспорте из РФ"
},
"right": {
"num": "19",
"label": "Наличие Фумигации на деревянной таре при экспорте из РФ"
}
},
{
"type": "left_12",
"num": "20",
"label": "Превышение габаритов дверного проема контейнеров 20DV, 40DV, 40HC"
}
]
},
"Авиаперевозка": {
"sheet": "Авиа Интерфейс",
"blocks": [
{
"type": "pair",
"left": {
"num": "4",
"label": "Страна, город, адрес забора"
},
"right": {
"num": "21",
"label": "Страна, город, точный адрес доставки, Место ТО в РФ"
}
},
{
"type": "pair",
"left": {
"num": "6",
"label": "Количество грузовых мест и вес, объем"
},
"right": {
"num": "7",
"label": "Габариты грузовых мест ДхШхВ"
}
},
{
"type": "pair",
"left": {
"num": "10",
"label": "Штабелирвоание с другими отправками"
},
"right": {
"num": "11",
"label": "Штабелирвоание между собой"
}
},
{
"type": "pair",
"left": {
"num": "9",
"label": "Наличие батарейк, газов, жидкостей, аэрозолей"
},
"right": {
"num": "13",
"label": "Батарейки в составе груза / отдельно"
}
},
{
"type": "pair",
"left": {
"num": "12",
"label": "MSDS"
},
"right": {
"num": "14",
"label": "DGM"
}
},
{
"type": "pair",
"left": {
"num": "15",
"label": "Название бренда"
},
"right": {
"num": "16",
"label": "Авторизационное письмо/разрешение на вывоз этих брендов из Китая"
}
},
{
"type": "pair",
"left": {
"num": "17",
"label": "Перелет через третью страну со сменой авинаклданых"
},
"right": {
"num": "18",
"label": "Наличие экспортной лицезии у отправителя"
}
},
{
"type": "pair",
"left": {
"num": "19",
"label": "Дополнительный сервис"
},
"right": {
"num": "20",
"label": "Экспедирование в аэропорту назначения"
}
},
{
"type": "pair",
"left": {
"num": "22",
"label": "Спец требования при доставке до адреса в РФ"
},
"right": {
"num": "23",
"label": "Таможенное оформление"
}
},
{
"type": "pair",
"left": {
"num": "24",
"label": "Место таможенного оформления при экспорте из РФ"
},
"right": {
"num": "25",
"label": "Наличие Фумигации на деревянной таре при экспорте из РФ"
}
}
]
}
}
}

View File

@ -1,154 +0,0 @@
from pypdf import PdfReader
from docx import Document
import openpyxl
from typing import Union
import io
import logging
from bs4 import BeautifulSoup
logger = logging.getLogger(__name__)
class DocumentProcessor:
@staticmethod
def _cell_to_text(v) -> str:
if v is None:
return ""
s = str(v).strip()
return s if s else ""
@staticmethod
def _sheet_rows_text_openpyxl(sheet) -> list[str]:
out: list[str] = []
for row in sheet.iter_rows(values_only=True):
vals = [DocumentProcessor._cell_to_text(c) for c in row]
vals = [x for x in vals if x]
if vals:
out.append(" | ".join(vals))
return out
@staticmethod
def _sheet_cols_text_openpyxl(sheet) -> list[str]:
out: list[str] = []
max_col = sheet.max_column or 0
max_row = sheet.max_row or 0
for c in range(1, max_col + 1):
vals: list[str] = []
for r in range(1, max_row + 1):
v = DocumentProcessor._cell_to_text(sheet.cell(r, c).value)
if v:
vals.append(v)
if vals:
col_letter = openpyxl.utils.get_column_letter(c)
out.append(f"COL {col_letter} TOP_DOWN: " + " || ".join(vals))
out.append(f"COL {col_letter} BOTTOM_UP: " + " || ".join(reversed(vals)))
return out
@staticmethod
def _sheet_rows_text_xlrd(sheet) -> list[str]:
out: list[str] = []
for row_idx in range(sheet.nrows):
row = sheet.row_values(row_idx)
vals = [DocumentProcessor._cell_to_text(c) for c in row]
vals = [x for x in vals if x]
if vals:
out.append(" | ".join(vals))
return out
@staticmethod
def _sheet_cols_text_xlrd(sheet) -> list[str]:
out: list[str] = []
for c in range(sheet.ncols):
vals: list[str] = []
for r in range(sheet.nrows):
v = DocumentProcessor._cell_to_text(sheet.cell_value(r, c))
if v:
vals.append(v)
if vals:
out.append(f"COL {c+1} TOP_DOWN: " + " || ".join(vals))
out.append(f"COL {c+1} BOTTOM_UP: " + " || ".join(reversed(vals)))
return out
def normalize_email_html(html_content: str) -> str:
"""
Очищает HTML письма и нормализует таблицы
"""
soup = BeautifulSoup(html_content, "html.parser")
# удаляем скрипты и стили
for tag in soup(["script", "style"]):
tag.decompose()
# нормализуем таблицы
for table in soup.find_all("table"):
table["style"] = "border-collapse: collapse; width: 100%;"
for cell in table.find_all(["td", "th"]):
cell["style"] = "border:1px solid #ccc;padding:6px;"
return str(soup)
def extract_text(self, content: bytes, filename: str) -> str:
ext = filename.lower().split('.')[-1]
# Изображения не обрабатываем
if ext in ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tiff', 'webp']:
return ""
if ext == 'pdf':
return self._extract_pdf(content)
elif ext in ['docx', 'doc']:
return self._extract_docx(content)
elif ext in ['xlsx', 'xls']:
return self._extract_excel(content)
elif ext == 'txt':
return content.decode('utf-8')
else:
raise ValueError(f"Unsupported format: {ext}")
def _extract_pdf(self, content: bytes) -> str:
pdf = PdfReader(io.BytesIO(content))
return "\n".join(page.extract_text() for page in pdf.pages)
def _extract_docx(self, content: bytes) -> str:
doc = Document(io.BytesIO(content))
return "\n".join(paragraph.text for paragraph in doc.paragraphs)
def _extract_excel(self, content: bytes) -> str:
try:
# сначала пробуем openpyxl (для .xlsx)
wb = openpyxl.load_workbook(io.BytesIO(content))
text = []
for sheet in wb.worksheets:
text.append(f"=== SHEET: {sheet.title} ===")
# Сохраняем совместимость: построчное чтение.
rows_text = self._sheet_rows_text_openpyxl(sheet)
if rows_text:
text.append("[ROWS]")
text.extend(rows_text)
# Новый режим: чтение по колонкам (общие данные часто внизу столбца).
cols_text = self._sheet_cols_text_openpyxl(sheet)
if cols_text:
text.append("[COLUMNS]")
text.extend(cols_text)
return "\n".join(text)
except Exception as e:
# если не получилось, возможно это .xls, пробуем xlrd
try:
import xlrd
workbook = xlrd.open_workbook(file_contents=content)
text = []
for sheet in workbook.sheets():
text.append(f"=== SHEET: {sheet.name} ===")
rows_text = self._sheet_rows_text_xlrd(sheet)
if rows_text:
text.append("[ROWS]")
text.extend(rows_text)
cols_text = self._sheet_cols_text_xlrd(sheet)
if cols_text:
text.append("[COLUMNS]")
text.extend(cols_text)
return "\n".join(text)
except ImportError:
logger.error("xlrd not installed, cannot parse .xls files")
return ""
except Exception as e2:
logger.error(f"Failed to parse Excel with xlrd: {e2}")
return ""

815
document_processor.py Normal file
View File

@ -0,0 +1,815 @@
import io
import os
import re
import csv
import tempfile
import subprocess
import logging
from typing import List
from bs4 import BeautifulSoup
from pypdf import PdfReader
from docx import Document
import openpyxl
import pdfplumber
from PIL import Image
import pytesseract
from striprtf.striprtf import rtf_to_text
logger = logging.getLogger(__name__)
class DocumentProcessor:
# =========================================================
# HELPERS
# =========================================================
@staticmethod
def _cleanup_text(text: str) -> str:
if not text:
return ""
text = text.replace("\xa0", " ")
text = text.replace("\t", " ")
text = re.sub(r"[ \t]+", " ", text)
text = re.sub(r"\n{3,}", "\n\n", text)
return text.strip()
@staticmethod
def _cell_to_text(v) -> str:
if v is None:
return ""
s = str(v).strip()
return s if s else ""
# =========================================================
# HTML
# =========================================================
@staticmethod
def normalize_email_html(html_content: str) -> str:
"""
Очищает HTML письма и нормализует таблицы
"""
soup = BeautifulSoup(
html_content,
"html.parser"
)
for tag in soup(["script", "style"]):
tag.decompose()
for table in soup.find_all("table"):
table["style"] = (
"border-collapse: collapse; width: 100%;"
)
for cell in table.find_all(["td", "th"]):
cell["style"] = (
"border:1px solid #ccc;padding:6px;"
)
return str(soup)
# =========================================================
# MAIN
# =========================================================
def extract_text(
self,
content: bytes,
filename: str
) -> str:
ext = filename.lower().split(".")[-1]
try:
# =================================================
# PDF
# =================================================
if ext == "pdf":
return self._extract_pdf(content)
# =================================================
# WORD
# =================================================
elif ext in ["docx", "docm"]:
return self._extract_docx(content)
elif ext == "doc":
return self._extract_doc(content)
elif ext == "rtf":
return self._extract_rtf(content)
# =================================================
# EXCEL
# =================================================
elif ext in ["xlsx", "xlsm", "xlsxm"]:
return self._extract_excel_openpyxl(content)
elif ext == "xls":
return self._extract_excel_xls(content)
elif ext == "csv":
return self._extract_csv(content)
# =================================================
# IMAGES / OCR
# =================================================
elif ext in [
"png",
"jpg",
"jpeg",
"gif",
"bmp",
"webp"
]:
return self._extract_image(content)
elif ext in ["tif", "tiff"]:
return self._extract_tiff(content)
# =================================================
# TEXT
# =================================================
elif ext == "txt":
try:
return content.decode("utf-8")
except Exception:
return content.decode(
"cp1251",
errors="ignore"
)
# =================================================
# UNKNOWN
# =================================================
logger.warning(
f"Unsupported attachment format: {ext}"
)
return ""
except Exception:
logger.exception(
f"Attachment processing failed: {filename}"
)
return ""
# =========================================================
# PDF
# =========================================================
def _extract_pdf(
self,
content: bytes
) -> str:
try:
parts = []
with pdfplumber.open(
io.BytesIO(content)
) as pdf:
for page_num, page in enumerate(
pdf.pages,
start=1
):
parts.append(
f"=== PAGE {page_num} ==="
)
# =====================================
# TEXT
# =====================================
try:
text = page.extract_text()
if text:
parts.append(text)
except Exception as e:
logger.warning(
f"PDF text extraction failed: {e}"
)
# =====================================
# TABLES
# =====================================
try:
tables = page.extract_tables()
for table_idx, table in enumerate(
tables,
start=1
):
parts.append(
f"=== TABLE {table_idx} ==="
)
for row in table:
if not row:
continue
cells = []
for cell in row:
if cell is None:
continue
txt = str(cell).strip()
txt = " ".join(
txt.split()
)
if txt:
cells.append(txt)
if cells:
parts.append(
" | ".join(cells)
)
except Exception as e:
logger.warning(
f"PDF table extraction failed: {e}"
)
text = "\n".join(parts)
return self._cleanup_text(text)
except Exception as e:
logger.error(f"PDF parse failed: {e}")
return ""
# =========================================================
# DOCX / DOCM
# =========================================================
def _extract_docx(
self,
content: bytes
) -> str:
try:
doc = Document(io.BytesIO(content))
parts = []
# =============================================
# PARAGRAPHS
# =============================================
for p in doc.paragraphs:
txt = p.text.strip()
if txt:
parts.append(txt)
# =============================================
# TABLES
# =============================================
for table_idx, table in enumerate(
doc.tables
):
parts.append(
f"=== TABLE {table_idx + 1} ==="
)
for row in table.rows:
cells = []
for cell in row.cells:
cell_parts = []
# =================================
# DIRECT CELL TEXT
# =================================
txt = "\n".join(
p.text.strip()
for p in cell.paragraphs
if p.text.strip()
)
txt = " ".join(txt.split())
if txt:
cell_parts.append(txt)
# =================================
# NESTED TABLES
# =================================
for nested_table in cell.tables:
for nested_row in nested_table.rows:
nested_vals = []
for nested_cell in nested_row.cells:
nested_txt = "\n".join(
p.text.strip()
for p in nested_cell.paragraphs
if p.text.strip()
)
nested_txt = " ".join(
nested_txt.split()
)
if nested_txt:
nested_vals.append(
nested_txt
)
if nested_vals:
cell_parts.append(
" || ".join(
nested_vals
)
)
# =================================
# FINAL CELL
# =================================
if cell_parts:
cells.append(
" <<<TABLE>>> ".join(
cell_parts
)
)
if cells:
parts.append(
" | ".join(cells)
)
text = "\n".join(parts)
return self._cleanup_text(text)
except Exception as e:
logger.error(f"DOCX parse failed: {e}")
return ""
# =========================================================
# DOC
# =========================================================
def _extract_doc(
self,
content: bytes
) -> str:
try:
with tempfile.TemporaryDirectory() as tmpdir:
input_path = os.path.join(
tmpdir,
"temp.doc"
)
with open(input_path, "wb") as f:
f.write(content)
subprocess.run(
[
"libreoffice",
"--headless",
"--convert-to",
"docx",
input_path,
"--outdir",
tmpdir,
],
check=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
converted_path = os.path.join(
tmpdir,
"temp.docx"
)
if not os.path.exists(
converted_path
):
logger.error(
"DOC conversion failed"
)
return ""
with open(
converted_path,
"rb"
) as f:
converted_content = f.read()
return self._extract_docx(
converted_content
)
except Exception as e:
logger.error(f"DOC parse failed: {e}")
return ""
# =========================================================
# RTF
# =========================================================
def _extract_rtf(
self,
content: bytes
) -> str:
try:
try:
text = content.decode("utf-8")
except Exception:
text = content.decode(
"cp1251",
errors="ignore"
)
text = rtf_to_text(text)
return self._cleanup_text(text)
except Exception as e:
logger.error(f"RTF parse failed: {e}")
return ""
# =========================================================
# XLSX
# =========================================================
def _extract_excel_openpyxl(
self,
content: bytes
) -> str:
try:
wb = openpyxl.load_workbook(
io.BytesIO(content),
data_only=True
)
text = []
for sheet in wb.worksheets:
text.append(
f"=== SHEET: {sheet.title} ==="
)
# =====================================
# MERGED CELLS
# =====================================
merged_ranges = list(
sheet.merged_cells.ranges
)
if merged_ranges:
text.append(
"=== MERGED CELLS ==="
)
for r in merged_ranges:
text.append(str(r))
# =====================================
# ROWS
# =====================================
text.append("[ROWS]")
for row in sheet.iter_rows(
values_only=True
):
vals = [
self._cell_to_text(c)
for c in row
]
vals = [x for x in vals if x]
if vals:
text.append(
" | ".join(vals)
)
# =====================================
# COLUMNS
# =====================================
text.append("[COLUMNS]")
max_col = sheet.max_column or 0
max_row = sheet.max_row or 0
for c in range(1, max_col + 1):
vals = []
for r in range(1, max_row + 1):
v = self._cell_to_text(
sheet.cell(r, c).value
)
if v:
vals.append(v)
if vals:
col_letter = (
openpyxl.utils
.get_column_letter(c)
)
text.append(
f"COL {col_letter}: "
+ " || ".join(vals)
)
return self._cleanup_text(
"\n".join(text)
)
except Exception as e:
logger.error(
f"XLSX parse failed: {e}"
)
return ""
# =========================================================
# XLS
# =========================================================
def _extract_excel_xls(
self,
content: bytes
) -> str:
try:
import xlrd
workbook = xlrd.open_workbook(
file_contents=content
)
text = []
for sheet in workbook.sheets():
text.append(
f"=== SHEET: {sheet.name} ==="
)
for row_idx in range(
sheet.nrows
):
row = sheet.row_values(
row_idx
)
vals = [
self._cell_to_text(c)
for c in row
]
vals = [x for x in vals if x]
if vals:
text.append(
" | ".join(vals)
)
return self._cleanup_text(
"\n".join(text)
)
except Exception as e:
logger.error(f"XLS parse failed: {e}")
return ""
# =========================================================
# CSV
# =========================================================
def _extract_csv(
self,
content: bytes
) -> str:
try:
try:
text = content.decode("utf-8")
except Exception:
text = content.decode(
"cp1251",
errors="ignore"
)
reader = csv.reader(
io.StringIO(text)
)
rows = []
for row in reader:
vals = [
str(x).strip()
for x in row
if str(x).strip()
]
if vals:
rows.append(
" | ".join(vals)
)
return self._cleanup_text(
"\n".join(rows)
)
except Exception as e:
logger.error(f"CSV parse failed: {e}")
return ""
# =========================================================
# OCR
# =========================================================
def _ocr_image(
self,
image: Image.Image
) -> str:
try:
text = pytesseract.image_to_string(
image,
lang="rus+eng",
config="--psm 6"
)
return self._cleanup_text(text)
except Exception as e:
logger.error(f"OCR failed: {e}")
return ""
# =========================================================
# IMAGE
# =========================================================
def _extract_image(
self,
content: bytes
) -> str:
try:
image = Image.open(
io.BytesIO(content)
)
return self._ocr_image(image)
except Exception as e:
logger.error(
f"Image parse failed: {e}"
)
return ""
# =========================================================
# TIFF
# =========================================================
def _extract_tiff(
self,
content: bytes
) -> str:
try:
image = Image.open(
io.BytesIO(content)
)
texts = []
for frame in range(
getattr(image, "n_frames", 1)
):
image.seek(frame)
texts.append(
self._ocr_image(image)
)
return self._cleanup_text(
"\n".join(texts)
)
except Exception as e:
logger.error(
f"TIFF parse failed: {e}"
)
return ""

View File

@ -39,6 +39,16 @@ def _row_cells(ws, r: int, max_c: int = 12) -> list[tuple[int, str]]:
return out return out
def _is_num_like(s: str) -> bool:
if not isinstance(s, str):
return False
t = s.strip()
if not t:
return False
# 1, 1., 1.0
return t.isdigit() or t.replace(".", "", 1).isdigit()
def parse_interface_sheet(ws) -> list[dict]: def parse_interface_sheet(ws) -> list[dict]:
"""Разбор листа интерфейса в последовательность визуальных блоков.""" """Разбор листа интерфейса в последовательность визуальных блоков."""
blocks: list[dict] = [] blocks: list[dict] = []
@ -50,22 +60,24 @@ def parse_interface_sheet(ws) -> list[dict]:
r += 1 r += 1
continue continue
# Заголовок: 7 ячеек в колонках 1,2,3,4,5,7,9 и все значения — «номера пунктов» # Заголовок верхнего ряда:
if ( # в новых версиях файла набор колонок может отличаться, поэтому
len(cells) == 7 # распознаём динамически: строка с номерами + следующая строка с подписями
and {c[0] for c in cells} == {1, 2, 3, 4, 5, 7, 9} # в тех же колонках.
and all(str(c[1]).strip().isdigit() or c[1].strip().replace(".", "").isdigit() for c in cells) cols = [c[0] for c in cells]
): vals = [c[1] for c in cells]
nums = [c[1] for c in sorted(cells, key=lambda x: (x[0] not in (1, 2, 3, 4, 5, 7, 9), x[0]))] if len(cells) >= 4 and all(_is_num_like(v) for v in vals):
# порядок как в Excel слева направо по колонкам
nums = [c[1] for c in sorted(cells, key=lambda x: x[0])]
r2 = r + 1 r2 = r + 1
cells2 = _row_cells(ws, r2) cells2 = _row_cells(ws, r2)
if len(cells2) == 7 and {c[0] for c in cells2} == {1, 2, 3, 4, 5, 7, 9}: map2 = {c: v for c, v in cells2}
labels = [c[1] for c in sorted(cells2, key=lambda x: x[0])] if all(c in map2 and str(map2[c]).strip() for c in cols):
blocks.append({"type": "header", "nums": nums, "labels": labels}) labels = [str(map2[c]).strip() for c in cols]
r += 2 # Если в следующей строке снова только числа — это не шапка.
continue if not all(_is_num_like(v) for v in labels):
nums = [str(v).strip() for v in vals]
blocks.append({"type": "header", "nums": nums, "labels": labels})
r += 2
continue
# Только правая пара (6 = номер, 7 = текст) — например «20 Место таможни» # Только правая пара (6 = номер, 7 = текст) — например «20 Место таможни»
if len(cells) == 2 and cells[0][0] == 6 and cells[1][0] == 7: if len(cells) == 2 and cells[0][0] == 6 and cells[1][0] == 7:

View File

@ -1,3 +1,5 @@
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse, Response from fastapi.responses import FileResponse, Response
from typing import List, Optional, Dict from typing import List, Optional, Dict
@ -20,7 +22,7 @@ from urllib.parse import quote
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
os.makedirs("/opt/rag-gemini/app/reports", exist_ok=True) os.makedirs("/opt/nek/app/reports", exist_ok=True)
SHIPPING_TYPES_FILE = os.path.join(os.path.dirname(__file__), "shipping_types.json") SHIPPING_TYPES_FILE = os.path.join(os.path.dirname(__file__), "shipping_types.json")
PROCESSED_SHIPPING_TYPES_FILE = os.path.join( PROCESSED_SHIPPING_TYPES_FILE = os.path.join(
os.path.dirname(__file__), "shipping_types_processed.json" os.path.dirname(__file__), "shipping_types_processed.json"
@ -167,6 +169,22 @@ app.add_middleware(
expose_headers=["Content-Disposition", "Content-Length"] expose_headers=["Content-Disposition", "Content-Length"]
) )
class CollapseDuplicatePathSlashesMiddleware(BaseHTTPMiddleware):
"""Схлопывает повторяющиеся слэши в path (например POST //process-outlook-emails → /process-outlook-emails)."""
async def dispatch(self, request: Request, call_next):
path = request.scope.get("path") or ""
if "//" in path:
collapsed = path
while "//" in collapsed:
collapsed = collapsed.replace("//", "/")
request.scope["path"] = collapsed
return await call_next(request)
app.add_middleware(CollapseDuplicatePathSlashesMiddleware)
class EmailAttachment(BaseModel): class EmailAttachment(BaseModel):
filename: str filename: str
@ -207,15 +225,12 @@ class CargoQueryResponse(BaseModel):
class AnalyzeCargoRequest(BaseModel): class AnalyzeCargoRequest(BaseModel):
email_ids: List[str] email_ids: List[str]
class CargoLearningRequest(BaseModel): class CargoLearningRequest(BaseModel):
"""Сохранение примера для обучения: переписка + структурированный ответ (как в отчёте).""" """Сохранение примера для обучения: переписка + структурированный ответ (как в отчёте)."""
structured_data: dict structured_data: dict
session_id: Optional[str] = None session_id: Optional[str] = None
context_preview: Optional[str] = None context_preview: Optional[str] = None
notes: Optional[str] = None notes: Optional[str] = None
@app.post("/record-cargo-learning") @app.post("/record-cargo-learning")
async def record_cargo_learning(req: CargoLearningRequest): async def record_cargo_learning(req: CargoLearningRequest):
""" """

View File

@ -1,92 +1,41 @@
import logging
import os
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse, Response from fastapi.responses import JSONResponse, Response
import httpx import httpx
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI() app = FastAPI()
UPSTREAM_URL = os.getenv( OPENROUTER_KEY = "sk-9cfed30eb6894df5b9a3ffb4b1fb956d"
"LLM_UPSTREAM_URL",
"https://llm.corp.septem.pro/v1/chat/completions",
).strip()
OPENROUTER_KEY = os.getenv("OPENROUTER_API_KEY", "").strip()
def _client_timeout() -> httpx.Timeout:
total = float(os.getenv("LLM_PROXY_TIMEOUT_SECONDS", "120"))
connect = float(os.getenv("LLM_PROXY_CONNECT_TIMEOUT", "15"))
return httpx.Timeout(total, connect=connect)
@app.post("/v1/chat/completions") @app.post("/v1/chat/completions")
async def proxy(req: Request): async def proxy(req: Request):
if not OPENROUTER_KEY: body = await req.json()
logger.error("OPENROUTER_API_KEY is not set (env or .env)")
return JSONResponse(
status_code=503,
content={
"error": "Service unavailable",
"details": "Set OPENROUTER_API_KEY for the LLM proxy (or add it to .env).",
},
)
try: async with httpx.AsyncClient() as client:
body = await req.json()
except Exception as e:
return JSONResponse(
status_code=400,
content={"error": "Invalid JSON", "details": str(e)},
)
verify = os.getenv("HTTPX_VERIFY", "true").lower() not in ("0", "false", "no")
async with httpx.AsyncClient(verify=verify) as client:
try: try:
r = await client.post( r = await client.post(
UPSTREAM_URL, "https://api.deepseek.com/chat/completions",
headers={ headers={
"Authorization": f"Bearer {OPENROUTER_KEY}", "Authorization": f"Bearer {OPENROUTER_KEY}",
"HTTP-Referer": os.getenv("LLM_HTTP_REFERER", "http://localhost"), "HTTP-Referer": "http://localhost",
"X-Title": os.getenv("LLM_PROXY_X_TITLE", "rag-engine"), "model": "deepseek-v4-flash",
"X-Title": "rag-engine"
}, },
json=body, json=body,
timeout=_client_timeout(), timeout=300,
)
except httpx.RequestError as e:
logger.error(
"LLM upstream unreachable (%s): %s",
UPSTREAM_URL,
e,
exc_info=True,
) )
except httpx.HTTPError as e:
# Ошибка сети / таймаут
return JSONResponse( return JSONResponse(
status_code=502, status_code=502,
content={ content={"error": "Bad gateway", "details": str(e)},
"error": "Bad gateway",
"details": str(e),
"upstream": UPSTREAM_URL,
"hint": "Проверьте VPN, DNS, доступность хоста и переменную LLM_UPSTREAM_URL.",
},
) )
if r.status_code >= 500: print(r.text)
logger.warning(
"LLM upstream HTTP %s, body (prefix): %s",
r.status_code,
(r.text or "")[:800],
)
# Если бэкенд всегда отвечает JSON:
# return JSONResponse(status_code=r.status_code, content=r.json())
# Универсальный вариант — пробрасываем «как есть»
return Response( return Response(
content=r.content, content=r.content,
status_code=r.status_code, status_code=r.status_code,

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,24 @@
"id": 1, "id": 1,
"name": "Автомобильная перевозка (LTL)", "name": "Автомобильная перевозка (LTL)",
"employee_email": "denis.fomin@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "denis.fomin@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "customs_clearance_place_export_rf"], "extra_required_fields": [
"hs_code",
"customs_clearance_place_export_rf"
],
"mandatory_counterparty_criteria": "По макету интерфейса обязательно отражать в письме контрагенту и запрашивать у клиента при отсутствии: название клиента; Incoterms; характер/наименование груза и код ТН ВЭД; страна, город, адрес забора; страна, город, точный адрес доставки; место таможенного оформления в РФ; количество грузовых мест и вес; габариты грузовых мест (Д×Ш×В).", "mandatory_counterparty_criteria": "По макету интерфейса обязательно отражать в письме контрагенту и запрашивать у клиента при отсутствии: название клиента; Incoterms; характер/наименование груза и код ТН ВЭД; страна, город, адрес забора; страна, город, точный адрес доставки; место таможенного оформления в РФ; количество грузовых мест и вес; габариты грузовых мест (Д×Ш×В).",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места в см или мм (длина × ширина × высота)\n8\tХарактер груза или наименование груза, код ТН ВЭД\n9\tСодержатся ли в грузе батарейки, газы под давлением, жидкости\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли груз нельзя штабелировать с другими грузами — можно ли штабелировать грузовые места между собой\n12\tЕсли груз — химия, литиевые батареи, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tЕсли есть батарейки — в составе груза или отдельно упакованы\n14\tЕсли груз из п.13 отгружается из материкового Китая по ж/д — дополнительно DGM\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tТребуется ли замена документов\n19\tСтрана, город, точный адрес доставки\n20\tМесто таможенного оформления в РФ", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места в см или мм (длина × ширина × высота) и их вес и объём\n8\tХарактер груза или наименование груза, код ТН ВЭД\n9\tСодержатся ли в грузе батарейки, газы под давлением, жидкости\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли груз нельзя штабелировать с другими грузами — можно ли штабелировать грузовые места между собой\n12\tЕсли груз — химия, литиевые батареи, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tЕсли есть батарейки — в составе груза или отдельно упакованы\n14\tЕсли груз из п.13 отгружается из материкового Китая авто транспортом — дополнительно DGM\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tТребуется ли замена документов\n19\tСтрана, город, точный адрес доставки\n20\tМесто таможенного оформления в РФ",
"keywords": ["ltl", "сборный трак", "догруз", "группаж авто", "less than truckload", "неполная фура", "авто ltl", "мелкий груз авто", "road ltl", "partial truckload"], "keywords": [
"ltl",
"сборный трак",
"догруз",
"группаж авто",
"less than truckload",
"неполная фура",
"авто ltl",
"мелкий груз авто",
"road ltl",
"partial truckload"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We are pleased to confirm the possibility of road freight (LTL) for your cargo under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Cargo weight: (Cargo weight) kg\n- Number of packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo description: (Cargo description)\n- HS code: (HS code)\n- Dangerous properties: (Dangerous properties)\n- MSDS required: (MSDS required)\n- Freight cost: (Estimated cost)\n- Estimated transit time: (Transit time)\n\nTo confirm the order and issue the invoice, please reply to this email or contact your manager.\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We are pleased to confirm the possibility of road freight (LTL) for your cargo under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Cargo weight: (Cargo weight) kg\n- Number of packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo description: (Cargo description)\n- HS code: (HS code)\n- Dangerous properties: (Dangerous properties)\n- MSDS required: (MSDS required)\n- Freight cost: (Estimated cost)\n- Estimated transit time: (Transit time)\n\nTo confirm the order and issue the invoice, please reply to this email or contact your manager.\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nБлагодарим вас за обращение в компанию SEPTEM. Для расчёта автомобильной перевозки (LTL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nПожалуйста, дополните данные по вашему грузу. Вы можете ответить на это письмо или загрузить недостающие документы через личный кабинет.\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nБлагодарим вас за обращение в компанию SEPTEM. Для расчёта автомобильной перевозки (LTL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nПожалуйста, дополните данные по вашему грузу. Вы можете ответить на это письмо или загрузить недостающие документы через личный кабинет.\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -14,10 +28,24 @@
"id": 2, "id": 2,
"name": "Автомобильная перевозка (FTL)", "name": "Автомобильная перевозка (FTL)",
"employee_email": "denis.fomin@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "denis.fomin@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "vehicle_type", "customs_clearance_place_export_rf"], "extra_required_fields": [
"hs_code",
"vehicle_type",
"customs_clearance_place_export_rf"
],
"mandatory_counterparty_criteria": "Обязательно в письме и при запросе клиенту: клиент; Incoterms; характер/наименование груза и ТН ВЭД; адрес забора; адрес доставки; место таможенного оформления в РФ; количество и типоразмер машин; вес груза в машине.", "mandatory_counterparty_criteria": "Обязательно в письме и при запросе клиенту: клиент; Incoterms; характер/наименование груза и ТН ВЭД; адрес забора; адрес доставки; место таможенного оформления в РФ; количество и типоразмер машин; вес груза в машине.",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер машин\n7\tВес груза в машине\n8\tЕсли нет данных о количестве машин — габариты каждого грузового места (Д×Ш×В в см или мм) и вес каждого места\n9\tХарактер груза или наименование груза, код ТН ВЭД\n10\tСодержатся ли в грузе батарейки, газы под давлением, жидкости\n11\tХимия, литиевые батареи, жидкости, аэрозоли, газы или порошки — MSDS\n12\tБатарейки — в составе груза или отдельно упакованы\n13\tОтгрузка из материкового Китая по ж/д — DGM\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (фитоконтроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления в РФ", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер машин\n7\tВес груза в машине и объём\n8\tЕсли нет данных о количестве машин — габариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n9\tХарактер груза или наименование груза, код ТН ВЭД\n10\tСодержатся ли в грузе батарейки, газы под давлением, жидкости\n11\tХимия, литиевые батареи, жидкости, аэрозоли, газы или порошки — MSDS\n12\tБатарейки — в составе груза или отдельно упакованы\n13\tОтгрузка из материкового Китая авто транспортом — DGM\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (фитоконтроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления в РФ",
"keywords": ["ftl", "полная фура", "целая машина", "full truckload", "отдельный автомобиль", "авто ftl", "тент фура целиком", "road ftl", "exclusive truck"], "keywords": [
"ftl",
"полная фура",
"целая машина",
"full truckload",
"отдельный автомобиль",
"авто ftl",
"тент фура целиком",
"road ftl",
"exclusive truck"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We are pleased to confirm the possibility of road freight (FTL) for your cargo under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Vehicle type: (Vehicle type)\n- Cargo weight: (Cargo weight) kg\n- Number of packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo description: (Cargo description)\n- HS code: (HS code)\n- Dangerous properties: (Dangerous properties)\n- MSDS required: (MSDS required)\n- Freight cost: (Estimated cost)\n- Transit time: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We are pleased to confirm the possibility of road freight (FTL) for your cargo under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Vehicle type: (Vehicle type)\n- Cargo weight: (Cargo weight) kg\n- Number of packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo description: (Cargo description)\n- HS code: (HS code)\n- Dangerous properties: (Dangerous properties)\n- MSDS required: (MSDS required)\n- Freight cost: (Estimated cost)\n- Transit time: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nБлагодарим за обращение в SEPTEM. Для расчёта автомобильной перевозки (FTL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nПожалуйста, дополните данные по грузу.\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nБлагодарим за обращение в SEPTEM. Для расчёта автомобильной перевозки (FTL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nПожалуйста, дополните данные по грузу.\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -25,10 +53,24 @@
"id": 3, "id": 3,
"name": "Морская перевозка (LCL)", "name": "Морская перевозка (LCL)",
"employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "stackable_with_others"], "extra_required_fields": [
"hs_code",
"stackable_with_others"
],
"mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест и вес; габариты Д×Ш×В; возможность штабелирования с другими отправками.", "mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест и вес; габариты Д×Ш×В; возможность штабелирования с другими отправками.",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к морской сборной перевозке (LCL): порт погрузки/выгрузки и морской этап явно указаны в переписке; без доминирования ж/д как основного этапа.", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес с объёмом\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к морской сборной перевозке (LCL): порт погрузки/выгрузки и морской этап явно указаны в переписке; без доминирования ж/д как основного этапа.",
"keywords": ["море lcl", "морская сборная", "морской lcl", "sea lcl", "сборный морской", "консолидация море", "groupage sea", "lcl порт", "морской группаж", "неполный контейнер море"], "keywords": [
"море lcl",
"морская сборная",
"морской lcl",
"sea lcl",
"сборный морской",
"консолидация море",
"groupage sea",
"lcl порт",
"морской группаж",
"неполный контейнер море"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm the possibility of sea freight (LCL) under the following terms:\n\n- Route: (Port of loading) -> (Port of discharge)\n- Shipment type: LCL\n- Cargo weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS code: (HS code)\n- Dangerous properties: (Dangerous properties)\n- MSDS: (MSDS required)\n- Freight: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm the possibility of sea freight (LCL) under the following terms:\n\n- Route: (Port of loading) -> (Port of discharge)\n- Shipment type: LCL\n- Cargo weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS code: (HS code)\n- Dangerous properties: (Dangerous properties)\n- MSDS: (MSDS required)\n- Freight: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта морской сборной перевозки (LCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nПожалуйста, дополните данные.\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта морской сборной перевозки (LCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nПожалуйста, дополните данные.\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -36,10 +78,22 @@
"id": 4, "id": 4,
"name": "Железнодорожная перевозка (LCL)", "name": "Железнодорожная перевозка (LCL)",
"employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "stackable_with_others"], "extra_required_fields": [
"hs_code",
"stackable_with_others"
],
"mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест и вес; габариты; штабелирование с другими отправками.", "mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест и вес; габариты; штабелирование с другими отправками.",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к ж/д сборной перевозке (LCL): станции/терминалы ж/д, контейнер сборный по ж/д; морской этап в запросе не основной.", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес с объёмом\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к ж/д сборной перевозке (LCL): станции/терминалы ж/д, контейнер сборный по ж/д; морской этап в запросе не основной.",
"keywords": ["жд lcl", "ж/д lcl", "rail lcl", "сборный контейнер жд", "сборная жд", "lcl поезд", "группаж жд", "железная дорога сборный"], "keywords": [
"жд lcl",
"ж/д lcl",
"rail lcl",
"сборный контейнер жд",
"сборная жд",
"lcl поезд",
"группаж жд",
"железная дорога сборный"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm rail freight (LCL) under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Shipment type: LCL\n- Weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm rail freight (LCL) under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Shipment type: LCL\n- Weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта железнодорожной сборной перевозки (LCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта железнодорожной сборной перевозки (LCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -47,10 +101,22 @@
"id": 5, "id": 5,
"name": "Мультимодальная перевозка море + ж/д (LCL)", "name": "Мультимодальная перевозка море + ж/д (LCL)",
"employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "stackable_with_others"], "extra_required_fields": [
"hs_code",
"stackable_with_others"
],
"mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест и вес; габариты; штабелирование с другими отправками.", "mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест и вес; габариты; штабелирование с другими отправками.",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nКритерии как для сборного груза при цепочке море и ж/д (интермодаль): в переписке явно присутствуют и морской, и железнодорожный этапы.", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес с объёмом\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nКритерии как для сборного груза при цепочке море и ж/д (интермодаль): в переписке явно присутствуют и морской, и железнодорожный этапы.",
"keywords": ["море жд", "море+жд", "море и жд", "sea rail", "интермодальн", "multimodal lcl", "морской и жд этап", "порт и станция сборный"], "keywords": [
"море жд",
"море+жд",
"море и жд",
"sea rail",
"интермодальн",
"multimodal lcl",
"морской и жд этап",
"порт и станция сборный"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm multimodal sea+rail (LCL) under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Modes: sea + rail (LCL)\n- Weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm multimodal sea+rail (LCL) under the following terms:\n\n- Route: (Pickup address) -> (Delivery address)\n- Modes: sea + rail (LCL)\n- Weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта мультимодальной перевозки (море + ж/д, LCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта мультимодальной перевозки (море + ж/д, LCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -58,10 +124,22 @@
"id": 6, "id": 6,
"name": "Морская перевозка (FCL)", "name": "Морская перевозка (FCL)",
"employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "container_type"], "extra_required_fields": [
"hs_code",
"container_type"
],
"mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество и типоразмер контейнеров; вес груза в контейнере.", "mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество и типоразмер контейнеров; вес груза в контейнере.",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и вес мест\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nМорской FCL: ISO-контейнеры под морской фрахт и погрузку на судно.", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере и объём\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и их вес и объём\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nМорской FCL: ISO-контейнеры под морской фрахт и погрузку на судно.",
"keywords": ["морской fcl", "море fcl", "sea fcl", "полный контейнер море", "морской контейнер", "fcl порт", "цельный контейнер море", "ocean fcl"], "keywords": [
"морской fcl",
"море fcl",
"sea fcl",
"полный контейнер море",
"морской контейнер",
"fcl порт",
"цельный контейнер море",
"ocean fcl"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm sea freight (FCL):\n\n- Port: (Port of loading) -> (Port of discharge)\n- Container: (Container type)\n- Weight: (Cargo weight) kg\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS/IMDG: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm sea freight (FCL):\n\n- Port: (Port of loading) -> (Port of discharge)\n- Container: (Container type)\n- Weight: (Cargo weight) kg\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS/IMDG: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта морской перевозки (FCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта морской перевозки (FCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -69,10 +147,21 @@
"id": 7, "id": 7,
"name": "Железнодорожная перевозка (FCL)", "name": "Железнодорожная перевозка (FCL)",
"employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "container_type"], "extra_required_fields": [
"hs_code",
"container_type"
],
"mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество и типоразмер контейнеров; вес груза в контейнере.", "mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество и типоразмер контейнеров; вес груза в контейнере.",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и вес мест\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nЖ/д FCL: ISO 20'/40' на платформах/вагонных комплектах (1520 мм); без обязательного морского этапа.", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере и объём\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и их вес и объём\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nЖ/д FCL: ISO 20'/40' на платформах/вагонных комплектах (1520 мм); без обязательного морского этапа.",
"keywords": ["жд fcl", "ж/д fcl", "rail fcl", "контейнер по жд целый", "полный контейнер жд", "fcl поезд", "вагон контейнер"], "keywords": [
"жд fcl",
"ж/д fcl",
"rail fcl",
"контейнер по жд целый",
"полный контейнер жд",
"fcl поезд",
"вагон контейнер"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm rail freight (FCL):\n\n- Route: (Pickup address) -> (Delivery address)\n- Container: (Container type)\n- Weight: (Cargo weight) kg\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm rail freight (FCL):\n\n- Route: (Pickup address) -> (Delivery address)\n- Container: (Container type)\n- Weight: (Cargo weight) kg\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта железнодорожной перевозки (FCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта железнодорожной перевозки (FCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -80,10 +169,20 @@
"id": 8, "id": 8,
"name": "Мультимодальная перевозка море + ж/д (FCL)", "name": "Мультимодальная перевозка море + ж/д (FCL)",
"employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch", "employee_email": "marina.eremina@timnet.ch, ekaterina.kochenkova@timnet.ch, Yana.Schkabrova@timnet.ch",
"extra_required_fields": ["hs_code", "container_type"], "extra_required_fields": [
"hs_code",
"container_type"
],
"mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество и типоразмер контейнеров; вес груза в контейнере.", "mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество и типоразмер контейнеров; вес груза в контейнере.",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и вес мест\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nМультимодальная перевозка море + ж/д (FCL): в запросе явно сочетаются морской и ж/д этапы с полным контейнером (интермодаль).", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере и объём\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и их вес и объём\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nМультимодальная перевозка море + ж/д (FCL): в запросе явно сочетаются морской и ж/д этапы с полным контейнером (интермодаль).",
"keywords": ["море жд fcl", "море+жд fcl", "sea rail fcl", "интермодальн fcl", "контейнер море и жд", "порт станция fcl"], "keywords": [
"море жд fcl",
"море+жд fcl",
"sea rail fcl",
"интермодальн fcl",
"контейнер море и жд",
"порт станция fcl"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm multimodal sea+rail (FCL):\n\n- Route: (Port of loading) / rail -> (Delivery address)\n- Container: (Container type)\n- Weight: (Cargo weight) kg\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm multimodal sea+rail (FCL):\n\n- Route: (Port of loading) / rail -> (Delivery address)\n- Container: (Container type)\n- Weight: (Cargo weight) kg\n- Cargo: (Cargo description)\n- HS: (HS code)\n- MSDS: (MSDS required)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта мультимодальной перевозки (море + ж/д, FCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта мультимодальной перевозки (море + ж/д, FCL) нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo"
}, },
@ -91,10 +190,26 @@
"id": 9, "id": 9,
"name": "Авиаперевозка", "name": "Авиаперевозка",
"employee_email": "evgeniy.domashnev@timnet.ch, olga.ermakova@timnet.ch, andrey.reshetnyak@timnet.ch, anastasia.fatkina@timnet.ch", "employee_email": "evgeniy.domashnev@timnet.ch, olga.ermakova@timnet.ch, andrey.reshetnyak@timnet.ch, anastasia.fatkina@timnet.ch",
"extra_required_fields": ["hs_code", "stackable_with_others", "total_volume_cbm", "dangerous_goods_clarification", "customs_clearance_place_export_rf"], "extra_required_fields": [
"hs_code",
"stackable_with_others",
"total_volume_cbm",
"dangerous_goods_clarification",
"customs_clearance_place_export_rf"
],
"mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест, вес и объём; габариты Д×Ш×В; штабелирование с другими отправками; сведения о батарейках, газах, жидкостях, аэрозолях; место таможенного оформления при экспорте из РФ (и прочие пункты чек-листа авиа по полному criteria).", "mandatory_counterparty_criteria": "Обязательно: клиент; Incoterms; характер груза и ТН ВЭД; адрес забора; адрес доставки; количество мест, вес и объём; габариты Д×Ш×В; штабелирование с другими отправками; сведения о батарейках, газах, жидкостях, аэрозолях; место таможенного оформления при экспорте из РФ (и прочие пункты чек-листа авиа по полному criteria).",
"criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес, объём\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, жидкости, хладоагенты, сухой лёд\n10\tШтабелирование с другими отправками\n11\tШтабелирование мест между собой\n12\tMSDS при химии, батареях, жидкостях, аэрозолях, порошках\n13\tБатарейки — в составе или отдельно\n14\tБатарейки и вылет из материкового Китая — DGM (Dangerous Goods Management) report\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tПерелёт через третью страну со сменой авианакладных\n18\tЭкспортная лицензия у отправителя\n19\tДоп. сервис: переупаковка, маркировка, логгеры и т.д.\n20\tКто осуществляет экспедирование в аэропорту прибытия (терминал, сборы авиакомпании)\n21\tСтрана, город, точный адрес доставки\n22\tВывоз из аэропорта — особые требования к автотранспорту, время подачи\n23\tНужно ли таможенное оформление\n24\tМесто таможенного оформления при экспорте из РФ\n25\tФумигация деревянной тары при экспорте из РФ", "criteria": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес, объём\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, жидкости, хладоагенты, сухой лёд\n10\tШтабелирование с другими отправками\n11\tШтабелирование мест между собой\n12\tMSDS при химии, батареях, жидкостях, аэрозолях, порошках\n13\tБатарейки — в составе или отдельно\n14\tБатарейки и вылет из материкового Китая — DGM (Dangerous Goods Management) report\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tПерелёт через третью страну со сменой авианакладных\n18\tЭкспортная лицензия у отправителя\n19\t Дополнительные сервисы (фитоконтроль и т.п.)\n20\tКто осуществляет экспедирование в аэропорту прибытия (терминал, сборы авиакомпании)\n21\tСтрана, город, точный адрес доставки\n22\tВывоз из аэропорта — особые требования к автотранспорту, время подачи\n23\tНужно ли таможенное оформление\n24\tМесто таможенного оформления при экспорте из РФ\n25\tФумигация деревянной тары при экспорте из РФ",
"keywords": ["авиа", "авиаперевозка", "самолёт", "air freight", "air cargo", "аэропорт", "flight", "авианакладная", "awb"], "keywords": [
"авиа",
"авиаперевозка",
"самолёт",
"air freight",
"air cargo",
"аэропорт",
"flight",
"авианакладная",
"awb"
],
"confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm air freight:\n\n- Route: (Pickup address) -> (Delivery address)\n- Weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS: (HS code)\n- Dangerous goods: (Dangerous properties)\n- MSDS: (MSDS required)\n- DGM (при опасном грузе / вылет из материкового Китая — по правилам перевозчика)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team", "confirmation_template": "Dear Partner!\n\nThank you for contacting SEPTEM. We confirm air freight:\n\n- Route: (Pickup address) -> (Delivery address)\n- Weight: (Cargo weight) kg\n- Packages: (Number of packages)\n- Volume: (Volume) m3\n- Dimensions: (Dimensions)\n- Cargo: (Cargo description)\n- HS: (HS code)\n- Dangerous goods: (Dangerous properties)\n- MSDS: (MSDS required)\n- DGM (при опасном грузе / вылет из материкового Китая — по правилам перевозчика)\n- Cost: (Estimated cost)\n- Transit: (Transit time)\n\nBest regards,\nSEPTEM Cargo Team",
"info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта авиаперевозки нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo" "info_request_template": "Уважаемый (Клиент)!\n\nДля расчёта авиаперевозки нам необходима следующая информация:\n\n(Необходимая информация)\n\nС уважением,\nКоманда SEPTEM Cargo"
} }

View File

@ -1,11 +1,11 @@
{ {
"Автомобильная перевозка (LTL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места в см или мм (длина × ширина × высота)\n8\tХарактер груза или наименование груза, код ТН ВЭД\n9\tСодержатся ли в грузе батарейки, газы под давлением, жидкости\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли груз нельзя штабелировать с другими грузами — можно ли штабелировать грузовые места между собой\n12\tЕсли груз — химия, литиевые батареи, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tЕсли есть батарейки — в составе груза или отдельно упакованы\n14\tЕсли груз из п.13 отгружается из материкового Китая по ж/д — дополнительно DGM\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tТребуется ли замена документов\n19\tСтрана, город, точный адрес доставки\n20\tМесто таможенного оформления в РФ", "Автомобильная перевозка (LTL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес, объём\n7\tГабариты каждого грузового места в см или мм (длина × ширина × высота) и их вес и объём\n8\tХарактер груза или наименование груза, код ТН ВЭД\n9\tСодержатся ли в грузе химия, батарейки, жидкости, аэрозоли, газы или порошки\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли груз нельзя штабелировать с другими грузами — можно ли штабелировать грузовые места между собой\n12\tЕсли груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tЕсли есть батарейки — в составе груза или отдельно упакованы\n14\tЕсли груз из п.13 отгружается из материкового Китая авто транспортом — дополнительно DGM\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tТребуется ли замена документов\n19\tСтрана, город, точный адрес доставки\n20\tМесто таможенного оформления в РФ",
"Автомобильная перевозка (FTL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер машин\n7\tВес груза в машине\n8\tЕсли нет данных о количестве машин — габариты каждого грузового места (Д×Ш×В в см или мм) и вес каждого места\n9\tХарактер груза или наименование груза, код ТН ВЭД\n10\tСодержатся ли в грузе батарейки, газы под давлением, жидкости\n11\tХимия, литиевые батареи, жидкости, аэрозоли, газы или порошки — MSDS\n12\tБатарейки — в составе груза или отдельно упакованы\n13\tОтгрузка из материкового Китая по ж/д — DGM\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (фитоконтроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления в РФ", "Автомобильная перевозка (FTL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер машин\n7\tВес груза в машине и объём\n8\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём \n9\tХарактер груза или наименование груза, код ТН ВЭД\n10\tСодержатся ли в грузе химия, батарейки, жидкости, аэрозоли, газы или порошки\n11\tЕсли груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n12\tБатарейки — в составе груза или отдельно упакованы\n13\tОтгрузка из материкового Китая авто транспортом — DGM\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (фитоконтроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\t Страна, город, точный адрес доставки",
"Морская перевозка (LCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к морской сборной перевозке (LCL): порт погрузки/выгрузки и морской этап явно указаны в переписке; без доминирования ж/д как основного этапа.", "Морская перевозка (LCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес и объём\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tХимия, батарейки, жидкости, аэрозоли, газы или порошки в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\t Если груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к морской сборной перевозке (LCL): порт погрузки/выгрузки и морской этап явно указаны в переписке; без доминирования ж/д как основного этапа.",
"Железнодорожная перевозка (LCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к ж/д сборной перевозке (LCL): станции/терминалы ж/д, контейнер сборный по ж/д; морской этап в запросе не основной.", "Железнодорожная перевозка (LCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес и объём\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tХимия, батарейки, жидкости, аэрозоли, газы или порошки в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\t Если груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nПрименимо к ж/д сборной перевозке (LCL): станции/терминалы ж/д, контейнер сборный по ж/д; морской этап в запросе не основной.",
"Мультимодальная перевозка море + ж/д (LCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест и вес\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, газы под давлением, жидкости в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\tХимия, литиевые батареи, жидкости, аэрозоли, газы, порошки — MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nКритерии как для сборного груза при цепочке море и ж/д (интермодаль): в переписке явно присутствуют и морской, и железнодорожный этапы.", "Мультимодальная перевозка море + ж/д (LCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес и объём\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tХимия, батарейки, жидкости, аэрозоли, газы или порошки в грузе\n10\tМожно ли штабелировать груз с другими отправками\n11\tЕсли нельзя с другими — можно ли штабелировать места между собой\n12\t Если груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tБатарейки — в составе или отдельно\n14\tОтгрузка из материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tДополнительные сервисы (фитоконтроль и т.п.)\n18\tСтрана, город, точный адрес доставки\n\nКритерии как для сборного груза при цепочке море и ж/д (интермодаль): в переписке явно присутствуют и морской, и железнодорожный этапы.",
"Морская перевозка (FCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и вес мест\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nМорской FCL: ISO-контейнеры под морской фрахт и погрузку на судно.", "Морская перевозка (FCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере и объём\n8\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tХимия, батарейки, жидкости, аэрозоли, газы или порошки в грузе\n11\t Если груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nМорской FCL: ISO-контейнеры под морской фрахт и погрузку на судно.",
"Железнодорожная перевозка (FCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и вес мест\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nЖ/д FCL: ISO 20'/40' на платформах/вагонных комплектах (1520 мм); без обязательного морского этапа.", "Железнодорожная перевозка (FCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере и объём\n8\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём \n9\tХарактер груза или наименование, код ТН ВЭД\n10\tХимия, батарейки, жидкости, аэрозоли, газы или порошки\n11\t Если груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nЖ/д FCL: ISO 20'/40' на платформах/вагонных комплектах (1520 мм); без обязательного морского этапа.",
"Мультимодальная перевозка море + ж/д (FCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере\n8\tЕсли нет данных о контейнерах — габариты каждого грузового места (Д×Ш×В) и вес мест\n9\tХарактер груза или наименование, код ТН ВЭД\n10\tБатарейки, газы, жидкости\n11\tMSDS при необходимости\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы (крепление в контейнере, фитосанитарный контроль и т.п.)\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n\nМультимодальная перевозка море + ж/д (FCL): в запросе явно сочетаются морской и ж/д этапы с полным контейнером (интермодаль).", "Мультимодальная перевозка море + ж/д (FCL)": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество и типоразмер контейнеров\n7\tВес груза в контейнере и объём\n8\tГабариты каждого грузового места (Д×Ш×В в см или мм) и их вес и объём \n9\tХарактер груза или наименование, код ТН ВЭД\n10\tХимия, батарейки, жидкости, аэрозоли, газы или порошки\n11\t Если груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n12\tБатарейки в составе или отдельно\n13\tИз материкового Китая по ж/д — Technical Description of Goods in Railway Transport\n14\tНазвание бренда\n15\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n16\tДополнительные сервисы\n17\tТребуется ли замена документов\n18\tСтрана, город, точный адрес доставки\n19\tМесто таможенного оформления при экспорте из РФ\n20\tФумигация деревянной тары при экспорте из РФ\n21\tПроверка габаритов грузовых мест на проходимость в дверной проём контейнеров 20DV, 40DV, 40HC\n22\tМультимодальная перевозка море + ж/д (FCL): в запросе явно сочетаются морской и ж/д этапы с полным контейнером (интермодаль).",
"Авиаперевозка": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес, объём\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)\n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, жидкости, хладоагенты, сухой лёд\n10\tШтабелирование с другими отправками\n11\tШтабелирование мест между собой\n12\tMSDS при химии, батареях, жидкостях, аэрозолях, порошках\n13\tБатарейки — в составе или отдельно\n14\tБатарейки и вылет из материкового Китая — DGM (Dangerous Goods Management) report\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tПерелёт через третью страну со сменой авианакладных\n18\tЭкспортная лицензия у отправителя\n19\tДоп. сервис: переупаковка, маркировка, логгеры и т.д.\n20\tКто осуществляет экспедирование в аэропорту прибытия (терминал, сборы авиакомпании)\n21\tСтрана, город, точный адрес доставки\n22\tВывоз из аэропорта — особые требования к автотранспорту, время подачи\n23\tНужно ли таможенное оформление\n24\tМесто таможенного оформления при экспорте из РФ\n25\tФумигация деревянной тары при экспорте из РФ" "Авиаперевозка": "1\tНазвание клиента\n2\tУсловия поставки Incoterms\n3\tДата готовности груза\n4\tСтрана, город, адрес забора\n5\tСтоимость груза\n6\tКоличество грузовых мест, вес, объём\n7\tГабариты каждого грузового места (Д×Ш×В в см или мм)и их вес и объём \n8\tХарактер груза или наименование, код ТН ВЭД\n9\tБатарейки, газы, жидкости, хладоагенты, сухой лёд\n10\tШтабелирование с другими отправками\n11\tШтабелирование мест между собой\n12\t Если груз содержит — химия, батарейки, жидкости, аэрозоли, газы или порошки — предоставить MSDS\n13\tБатарейки — в составе или отдельно\n14\tБатарейки и вылет из материкового Китая — DGM (Dangerous Goods Management) report\n15\tНазвание бренда\n16\tЕсли бренд зарегистрирован в таможенной системе Китая — есть ли у отправителя авторизационное письмо/разрешение на вывоз бренда\n17\tПерелёт через третью страну со сменой авианакладных\n18\tЭкспортная лицензия у отправителя\n19\tДополнительные сервисы (фитоконтроль и т.п.)\n20\tКто осуществляет экспедирование в аэропорту прибытия (терминал, сборы авиакомпании)\n21\tСтрана, город, точный адрес доставки\n22\tВывоз из аэропорта — особые требования к автотранспорту, время подачи\n23\tНужно ли таможенное оформление\n24\tМесто таможенного оформления при экспорте из РФ\n25\tФумигация деревянной тары при экспорте из РФ"
} }

View File

@ -325,11 +325,24 @@ def collect_extra_required_missing_for_template(shipment: Dict, template_obj: Di
if v is None or (isinstance(v, str) and not str(v).strip()): if v is None or (isinstance(v, str) and not str(v).strip()):
out.append(field) out.append(field)
continue continue
if field == "customs_clearance_place_export_rf": if field == "customs_clearance_place_export_rf":
direction = shipment.get("shipment_direction")
# только экспорт из РФ
if direction != "export":
continue
v = shipment.get("customs_clearance_place_export_rf") v = shipment.get("customs_clearance_place_export_rf")
if v is None or (isinstance(v, str) and not str(v).strip()):
if v is None or (
isinstance(v, str) and not str(v).strip()
):
out.append(field) out.append(field)
continue continue
if field == "total_volume_cbm": if field == "total_volume_cbm":
val = shipment.get("total_volume_cbm") val = shipment.get("total_volume_cbm")
if val is None or val == "": if val is None or val == "":
@ -1155,17 +1168,44 @@ def format_shipment_for_template(
dims = shipment.get("dimensions", []) dims = shipment.get("dimensions", [])
if isinstance(dims, list) and dims: if isinstance(dims, list) and dims:
dim_strings = [] dim_strings = []
for d in dims: for idx, d in enumerate(dims, start=1):
if isinstance(d, dict):
l = d.get("length_cm") if not isinstance(d, dict):
w = d.get("width_cm") continue
h = d.get("height_cm")
if l and w and h: l = d.get("length_cm")
dim_strings.append(f"{l}×{w}×{h} {dim_unit}") w = d.get("width_cm")
h = d.get("height_cm")
sizes = [str(v) for v in (l, w, h) if v not in (None, "", 0)]
if not sizes:
continue
parts = [
f"Место {idx}: {'×'.join(sizes)} см"
]
weight = d.get("weight_kg")
if weight not in (None, "", 0):
if template_locale == "en":
parts.append(f"weight {weight} kg")
else:
parts.append(f"вес {weight} кг")
volume = d.get("volume_cbm")
if volume not in (None, "", 0):
if template_locale == "en":
parts.append(f"volume {volume} cbm")
else:
parts.append(f"объём {volume} м³")
dim_strings.append(" | ".join(parts))
if dim_strings: if dim_strings:
data["dimensions_str"] = "; ".join(dim_strings) data["dimensions_str"] = "; ".join(dim_strings)
@ -1701,16 +1741,34 @@ def render_shipment_criteria_checklist(
seen = set() seen = set()
if isinstance(dims, list): if isinstance(dims, list):
for d in dims:
if isinstance(d, dict): for idx, d in enumerate(dims, start=1):
l = d.get("length_cm")
w = d.get("width_cm") if not isinstance(d, dict):
h = d.get("height_cm") continue
if l and w and h:
key = f"{l}x{w}x{h}".lower() l = d.get("length_cm")
if key not in seen: w = d.get("width_cm")
seen.add(key) h = d.get("height_cm")
parts.append(f"{l}×{w}×{h} см")
sizes = [str(v) for v in (l, w, h) if v not in (None, "", 0)]
if not sizes:
continue
weight = d.get("weight_kg")
volume = d.get("volume_cbm")
line_parts = [
f"Место {idx}: {'×'.join(sizes)} см"
]
if weight not in (None, "", 0):
line_parts.append(f"вес {weight} кг")
if volume not in (None, "", 0):
line_parts.append(f"объём {volume} м³")
parts.append(" | ".join(line_parts))
return "; ".join(parts) if parts else NO_INFO_TEXT return "; ".join(parts) if parts else NO_INFO_TEXT
@ -1727,6 +1785,191 @@ def render_shipment_criteria_checklist(
return vehicle_dims return vehicle_dims
return NO_INFO_TEXT return NO_INFO_TEXT
def _format_dimensions_with_weight_volume(sh: Dict) -> str:
"""
Габариты каждого места + вес + объём.
"""
dims = sh.get("dimensions")
if not isinstance(dims, list) or not dims:
return NO_INFO_TEXT
parts = []
for idx, d in enumerate(dims, start=1):
if not isinstance(d, dict):
continue
l = d.get("length_cm")
w = d.get("width_cm")
h = d.get("height_cm")
weight = d.get("weight_kg")
volume = d.get("volume_cbm")
row = []
sizes = [
str(v)
for v in (l, w, h)
if v not in (None, "", 0)
]
if sizes:
row.append(f"{'×'.join(sizes)} см")
if weight not in (None, "", 0):
row.append(f"вес {weight} кг")
if volume not in (None, "", 0):
row.append(f"объём {volume} м³")
if row:
parts.append(f"Место {idx}: " + " | ".join(row))
if not parts:
return NO_INFO_TEXT
return "; ".join(parts)
def _filtered_door_clearance(sh: Dict) -> str:
"""
Показывает только проблемные места.
"""
raw = door_clearance_summary(sh)
if (
"Нет габаритов" in raw
or "невозможна" in raw
):
return raw
import re
place_blocks = re.findall(
r"(Место\s+\d+.*?)(?=Место\s+\d+|$)",
raw,
flags=re.S,
)
failed = []
for blk in place_blocks:
if "не проходит" not in blk:
continue
parts = []
for part in blk.split(";"):
part = part.strip()
if (
"не проходит" in part
or part.startswith("Место")
):
parts.append(part)
txt = "; ".join(parts)
if txt:
failed.append(txt)
# =====================================================
# Все проходят
# =====================================================
if not failed:
ct = (sh.get("container_type") or "").strip()
if ct:
return (
f"Все грузовые места проходят "
f"в дверной проём контейнера(ов) {ct}."
)
return (
"Все грузовые места проходят "
"в дверной проём контейнеров."
)
# =====================================================
# Есть проблемы
# =====================================================
return " ".join(failed)
# --- далее оригинальная функция _answer_for_criterion с правками ---
def _answer_for_criterion(criterion_text: str) -> str:
c = criterion_text.lower()
# ... существующие проверки до блока с габаритами ...
# === ИЗМЕНЕНИЕ: критерии с общим весом и объёмом ===
if "вес" in c and "количество" not in c and "габарит" not in c:
w = shipment.get("total_weight_kg")
weight_str = f"{w} кг" if (w is not None and str(w).strip() not in ("", "0", "0.0")) else ""
vol_str = _format_volume_cbm()
if weight_str and vol_str != NO_INFO_TEXT:
return f"{weight_str}, объём: {vol_str}"
elif weight_str:
return weight_str
elif vol_str != NO_INFO_TEXT:
return f"Объём: {vol_str}"
return NO_INFO_TEXT
if "общий объ" in c or "общий объём" in c or "общий объем" in c:
vol = _format_volume_cbm()
w = shipment.get("total_weight_kg")
weight_str = f"{w} кг" if (w is not None and str(w).strip() not in ("", "0", "0.0")) else ""
if vol != NO_INFO_TEXT and weight_str:
return f"{vol}, вес: {weight_str}"
elif vol != NO_INFO_TEXT:
return vol
elif weight_str:
return f"Вес: {weight_str}"
return NO_INFO_TEXT
# ... блоки с габаритами транспортных средств (без изменений) ...
if "габарит" in c and (
"транспортн" in c
or "машин" in c
or "средств" in c
or "кузов" in c
or "прицеп" in c
or "полуприцеп" in c
):
return _format_dimensions_any() # только размеры
# === ИЗМЕНЕНИЕ: габариты грузовых мест добавляем вес и объём ===
if "габарит" in c and "грузов" in c and "мест" in c:
return _format_dimensions_with_weight_volume(shipment)
if (
("палл" in c or "палет" in c or "короб" in c or "carton" in c or "box" in c)
and ("габарит" in c or "размер" in c or "size" in c or "dimension" in c)
):
return _format_dimensions_with_weight_volume(shipment)
# общий fallback для габаритов (если не транспорт)
if "габарит" in c:
return _format_dimensions_with_weight_volume(shipment)
# ... критерии про проём контейнера ...
if ("проём" in c or "проем" in c) and (
"контейнер" in c
or "20dv" in c
or "40dv" in c
or "40hc" in c
or "проходимость" in c
):
return _filtered_door_clearance(shipment)
def _join_desc_and_hs(sh: Dict) -> str: def _join_desc_and_hs(sh: Dict) -> str:
desc = (sh.get("cargo_description") or "").strip() desc = (sh.get("cargo_description") or "").strip()
hs = (sh.get("hs_code") or "").strip() hs = (sh.get("hs_code") or "").strip()
@ -1830,7 +2073,18 @@ def render_shipment_criteria_checklist(
def _answer_for_criterion(criterion_text: str) -> str: def _answer_for_criterion(criterion_text: str) -> str:
c = criterion_text.lower() c = criterion_text.lower()
# =====================================================
# Проверка дверного проёма контейнера (п.21)
# =====================================================
if (
"дверной проём" in c
or "дверной проем" in c
or "20dv" in c
or "40dv" in c
or "40hc" in c
):
return _filtered_door_clearance(shipment)
# Любой критерий с "габарит" должен в приоритете возвращать размеры, а не перехватываться ветками по весу. # Любой критерий с "габарит" должен в приоритете возвращать размеры, а не перехватываться ветками по весу.
if "габарит" in c: if "габарит" in c:
return _format_dimensions_any() return _format_dimensions_any()
@ -1897,14 +2151,68 @@ def render_shipment_criteria_checklist(
return NO_INFO_TEXT return NO_INFO_TEXT
return str(pkg).strip() return str(pkg).strip()
# =========================================================
# ОБЩИЙ ОБЪЁМ
# =========================================================
if "общий объ" in c or "общий объём" in c or "общий объем" in c: if "общий объ" in c or "общий объём" in c or "общий объем" in c:
return _format_volume_cbm()
vol = _format_volume_cbm()
w = shipment.get("total_weight_kg")
weight_ok = (
w is not None
and str(w).strip() not in ("", "0", "0.0")
)
weight_str = f"{w} кг" if weight_ok else ""
# есть и объём и вес
if vol != NO_INFO_TEXT and weight_str:
return f"{vol}, вес: {weight_str}"
# только объём
if vol != NO_INFO_TEXT:
return vol
# только вес
if weight_str:
return f"Вес: {weight_str}"
return NO_INFO_TEXT
# =========================================================
# ОБЩИЙ ВЕС
# =========================================================
if "вес" in c and "количество" not in c: if "вес" in c and "количество" not in c:
w = shipment.get("total_weight_kg") w = shipment.get("total_weight_kg")
if w is None or str(w).strip() in ("", "0", "0.0"):
return NO_INFO_TEXT weight_ok = (
return f"{w} кг" w is not None
and str(w).strip() not in ("", "0", "0.0")
)
weight_str = f"{w} кг" if weight_ok else ""
vol = _format_volume_cbm()
# есть и вес и объём
if weight_str and vol != NO_INFO_TEXT:
return f"{weight_str}, объём: {vol}"
# только вес
if weight_str:
return weight_str
# только объём
if vol != NO_INFO_TEXT:
return f"Объём: {vol}"
return NO_INFO_TEXT
if ("проём" in c or "проем" in c) and ( if ("проём" in c or "проем" in c) and (
"контейнер" in c "контейнер" in c
@ -1950,19 +2258,23 @@ def render_shipment_criteria_checklist(
# Перечень DG (авиа п.9, море/авто и т.д.) и формулировки интерфейса («Наличие батарейк, газов…»). # Перечень DG (авиа п.9, море/авто и т.д.) и формулировки интерфейса («Наличие батарейк, газов…»).
if ( if (
"содержатся ли в грузе" in c "msds" not in c
or "опасные вещества" in c and "dgm" not in c
or "опасные свойства" in c and (
or ( "содержатся ли в грузе" in c
("батарейки" in c or "батарейк" in c) or "опасные вещества" in c
and ( or "опасные свойства" in c
"газы" in c or (
or "газов" in c ("батарейки" in c or "батарейк" in c)
or "жидкост" in c and (
or "аэрозол" in c "газы" in c
or "хладоагент" in c or "газов" in c
or "сухой лёд" in c or "жидкост" in c
or "сухой лед" in c or "аэрозол" in c
or "хладоагент" in c
or "сухой лёд" in c
or "сухой лед" in c
)
) )
) )
): ):
@ -1974,15 +2286,27 @@ def render_shipment_criteria_checklist(
return _yes_no_or_no_info(shipment.get("stackable_with_others")) return _yes_no_or_no_info(shipment.get("stackable_with_others"))
if "msds" in c or "паспорт безопасности" in c: if "msds" in c or "паспорт безопасности" in c:
msds_negative = _msds_negative_phrase() msds_negative = _msds_negative_phrase()
if msds_negative: if msds_negative:
return msds_negative return msds_negative
if "батаре" in c and _has_batteries(shipment) is not True:
# Если батареек нет, документ по батарейкам не нужен. msds_required = shipment.get("msds_required")
if shipment.get("msds_required") is False:
return "Не нужен" # =====================================
return NO_INFO_TEXT # Явно не нужен
return _required_doc(shipment.get("msds_required"), "msds") # =====================================
if msds_required is False:
return "Не нужен"
# =====================================
# Нужен / найден
# =====================================
return _required_doc(msds_required, "msds")
if re.search(r"(?<![a-z])dgm(?![a-z])", c): if re.search(r"(?<![a-z])dgm(?![a-z])", c):
if "батаре" in c and _has_batteries(shipment) is not True: if "батаре" in c and _has_batteries(shipment) is not True:
if shipment.get("dgm_report_required") is False: if shipment.get("dgm_report_required") is False:
@ -2021,7 +2345,38 @@ def render_shipment_criteria_checklist(
return build_documents_summary(shipment) return build_documents_summary(shipment)
if "бренд" in c and "авторизац" in c: if "бренд" in c and "авторизац" in c:
return format_brand_authorization_summary(shipment)
docs = shipment.get("documents_found", {}) or {}
found_docs = docs.get("brand_authorization", []) or []
if found_docs:
filenames = [
d.get("filename", "")
for d in found_docs
if d.get("filename")
]
if filenames:
return (
"Нужно "
f"(документ найден: {', '.join(filenames)})"
)
return "Нужно (документ найден)"
flag = shipment.get("brand_authorization_letter")
if flag is True:
return "Нужно (документ не найден)"
elif flag is False:
return "Не нужно"
else:
return NO_INFO_TEXT
if "название бренда" in c or ( if "название бренда" in c or (
"бренд" in c "бренд" in c
and "авторизац" not in c and "авторизац" not in c
@ -2032,8 +2387,23 @@ def render_shipment_criteria_checklist(
if "лицензия экспорт" in c: if "лицензия экспорт" in c:
return _yes_no_or_no_info(shipment.get("exporter_has_export_license")) return _yes_no_or_no_info(shipment.get("exporter_has_export_license"))
if "трансшипмент" in c: if (
return _yes_no_or_no_info(shipment.get("transshipment_with_third_country")) "трансшипмент" in c
or "треть" in c
or "сменой авианаклад" in c
or "разрыв наклад" in c
):
transshipment = shipment.get("transshipment_with_third_country")
if transshipment is True:
return "Нужен"
elif transshipment is False:
return "Не нужен"
else:
return NO_INFO_TEXT
if "дополнительный сервис" in c or "дополнительные услуги" in c or "дополнительные сервисы" in c or "сервисы" in c: if "дополнительный сервис" in c or "дополнительные услуги" in c or "дополнительные сервисы" in c or "сервисы" in c:
extras = shipment.get("additional_services") extras = shipment.get("additional_services")
@ -2082,9 +2452,13 @@ def render_shipment_criteria_checklist(
return NO_INFO_TEXT return NO_INFO_TEXT
if "батарейки" in c and ("упаков" in c or "отдель" in c): if "батарейки" in c and ("упаков" in c or "отдель" in c):
if _has_batteries(shipment) is not True:
return NO_INFO_TEXT battery_mode = shipment.get("battery_mode")
return _yes_no_or_no_info(shipment.get("batteries_packed_separately"))
if battery_mode:
return battery_mode
return NO_INFO_TEXT
if "тип транспорта" in c: if "тип транспорта" in c:
return (shipment.get("vehicle_type") or "").strip() or NO_INFO_TEXT return (shipment.get("vehicle_type") or "").strip() or NO_INFO_TEXT
@ -2393,12 +2767,37 @@ def display_overview(report: Dict):
with col1 if i < mid else col2: with col1 if i < mid else col2:
label = FIELD_LABELS.get(key, key) label = FIELD_LABELS.get(key, key)
if key in ("dimensions", "vehicle_dimensions"): if key == "dimensions":
dims = [] dims = []
for d in value:
if isinstance(d, dict) and d.get('length_cm') and d.get('width_cm') and d.get('height_cm'): for idx, d in enumerate(value, start=1):
dims.append(f"{d['length_cm']}×{d['width_cm']}×{d['height_cm']} см")
if not isinstance(d, dict):
continue
l = d.get("length_cm")
w = d.get("width_cm")
h = d.get("height_cm")
sizes = [str(v) for v in (l, w, h) if v not in (None, "", 0)]
if not sizes:
continue
parts = [
f"Место {idx}: {'×'.join(sizes)} см"
]
if d.get("weight_kg") not in (None, "", 0):
parts.append(f"вес {d['weight_kg']} кг")
if d.get("volume_cbm") not in (None, "", 0):
parts.append(f"объём {d['volume_cbm']} м³")
dims.append(" | ".join(parts))
value_str = "; ".join(dims) if dims else NO_INFO_TEXT value_str = "; ".join(dims) if dims else NO_INFO_TEXT
elif key == "criteria" and isinstance(value, str): elif key == "criteria" and isinstance(value, str):
# criteria может быть: # criteria может быть:
# - сырой: "1\tНазвание...\n2\t..." # - сырой: "1\tНазвание...\n2\t..."
@ -2423,34 +2822,61 @@ def display_overview(report: Dict):
elif key == "cargo_ready_date": elif key == "cargo_ready_date":
value_str = format_cargo_ready_date_for_display(shipment) value_str = format_cargo_ready_date_for_display(shipment)
elif isinstance(value, bool): elif isinstance(value, bool):
# Только для документов: "нужен/не нужен"
doc_bool_keys = {"msds_required", "dgm_report_required", "brand_authorization_letter"}
base_str = ("нужен" if value else "не нужен") if key in doc_bool_keys else ("✅ Да" if value else "❌ Нет")
docs = shipment.get("documents_found", {})
doc_map = { if key == "brand_authorization_letter":
"msds_required": "msds",
"dgm_report_required": "dgm",
"brand_authorization_letter": "brand_authorization",
}
if key in doc_map and value: value_str = format_brand_authorization_summary(shipment)
doc_type = doc_map[key]
found_docs = docs.get(doc_type, [])
if found_docs:
filenames = [d["filename"] for d in found_docs]
value_str = f"{base_str} (документ найден: {', '.join(filenames)})"
else:
value_str = f"{base_str} (документ не найден)"
else: else:
value_str = base_str # Только для документов: "нужен/не нужен"
doc_bool_keys = {
"msds_required",
"dgm_report_required",
"brand_authorization_letter"
}
base_str = (
"нужен" if value else "не нужен"
) if key in doc_bool_keys else (
"✅ Да" if value else "❌ Нет"
)
docs = shipment.get("documents_found", {})
doc_map = {
"msds_required": "msds",
"dgm_report_required": "dgm",
"brand_authorization_letter": "brand_authorization",
}
if key in doc_map and value:
doc_type = doc_map[key]
found_docs = docs.get(doc_type, [])
if found_docs:
filenames = [
d["filename"]
for d in found_docs
]
value_str = (
f"{base_str} "
f"(документ найден: {', '.join(filenames)})"
)
else:
value_str = (
f"{base_str} "
f"(документ не найден)"
)
else:
value_str = base_str
elif isinstance(value, list): elif isinstance(value, list):
value_str = ", ".join(str(v) for v in value) if value else NO_INFO_TEXT value_str = ", ".join(str(v) for v in value) if value else NO_INFO_TEXT
elif value == None or value == "": elif value == None or value == "":