Sync Workflows
Synchronize Automail with Autoform in a controlled way
How to use it?
Example
try:
from _init import * # DEV env
except ImportError:
from configurations.workflow_env import * # PROD env
from polygon.apps.app_autoform.sync import do_bulk_sync
def get_field_definitions_ecopack_primary_packaging():
field_definitions_ecopack_primary_packaging = global_variables.field_definitions_ecopack_primary_packaging
valid_material_list = []
for cookie_category in custom_models.Cookie.objects.all():
valid_material_list.append(
{
"conditions": [
{
"function": "eq",
"params": {
"value": "category__label",
"target": cookie_category.label,
},
},
{
"function": "in",
"params": {
"value": "material__name",
"list": list(
custom_models.CookieMaterial.objects.filter(
material_type=cookie_category.material_type,
).values_list(
"name",
flat=True,
)
.distinct()
),
},
},
],
"value": True,
},
)
field_definitions_ecopack_primary_packaging["material__name"]["configured_validations"] = [
{
"function": "valid",
"message": "The selected material is not valid for the packaging type of the same row.",
"params": {
"if": valid_material_list,
"else": {
"value": False,
},
},
}
]
return field_definitions_ecopack_primary_packaging
def get_autoform_navs(monitor):
autoform_navs = []
def get_hanger_card_elements(card_number):
card_config = []
hanger_reference_config = {
"item_name": "reference",
"class": "col-6",
"type": "select",
"options_lists": "hanger_reference_options_config",
"attributes": {
"required": True,
"data-live-search": "true",
"title_map": {"en": "Select One..."},
"focusout": "update_options",
},
"related_item_ref": f"hanger_supplier_size_{card_number}",
"model": custom_models.EcoPackMonitorPrimaryPackaging,
}
hanger_supplier_size_config = {
"item_ref": f"hanger_supplier_size_{card_number}",
"item_name": "supplier_size",
"class": "col-6",
"type": "select",
"attributes": {
"required": True,
"data-live-search": "true",
"title_map": {"en": "Select One..."},
},
"model": custom_models.EcoPackMonitorPrimaryPackaging,
}
card_config.append(hanger_reference_config)
card_config.append(hanger_supplier_size_config)
return card_config
def add_primary_packaging_tab(monitor):
def get_hanger_group_children():
hanger_children = []
hanger_children.append(
{
"item_name": "has_hanger",
"label_map": {
"en": "Packaging that is part of the product<br><strong>Is there a referenced hanger?</strong>"
},
"attributes": {
"focusout": "append",
},
"model": custom_models.EcoPackMonitorPrimaryPackaging,
"children": [
{
"parent_value": True,
"category": "card",
"class": "mb-3",
"title_map": {"en": f"Select your Hanger Configurations"},
"description_map": {
"en": "Please select in the order of <strong>Reference > Supplier (Size)</strong>"
},
"children": [
{
"category": "group",
"class": "card-body mr-0 ml-0 form-row my-0 py-0 border-top pt-3",
"children": get_hanger_card_elements(1),
}
],
"model": custom_models.EcoPackMonitorPrimaryPackaging,
"load_method": {
"function": "upsert",
"params": {
"key_fields": {
"ecopackmonitor_id": lambda monitor: monitor.id,
},
"defaults": {
"reference": {
"function": "get_child_item_value",
},
"supplier_size": {
"function": "get_child_item_value",
},
},
},
},
},
],
},
)
return hanger_children
autoform_navs.append(
{
"label_map": {"en": "Primary Packaging"},
"children": [
{
"item_ref": "g_hanger_append",
"category": "group",
"class": "group_to_append",
"children": get_hanger_group_children(),
},
{
"item_name": "primary_packaging",
"label_map": {
"en": """
<strong>Instructions</strong>
<ul>
<li><small>Please note that you should declare your hanger (the plastic hanger and the metal hook if there is) in this table ONLY if your hanger ref + supplier is not present in the above hanger section </small></li>
<li><small>If there is an inner polybag (inner packing), DO NOT declare it in the table below</small></li>
</ul>
<strong>Declare OTHER Primary Packaging Categories in the Table Below (like hangtags, plastic ties etc. )</strong>
"""
},
"attributes": {"required": True},
"table_props": {
"model": custom_models.EcoPackForm,
"queryset": custom_models.EcoPackForm.objects.filter(
ecopackmonitor=monitor
),
"field_definitions": get_field_definitions_ecopack_primary_packaging(),
"target_rows": 20,
"table_settings": {
"permissions": {
"delete": {
"allowed": True,
}
},
},
},
},
],
},
)
def add_secondary_packaging_tab():
def get_secondary_packaging_questions():
questions = []
questions.append(
{
"item_name": "has_inner_polybag",
"label_map": {
"en": "Secondary packaging is the packaging of the master & inner cartons<br><strong>Do you use an inner polybag (not master carton polybag) for the SPCB & inner packing?</strong>"
},
"model": custom_models.EcoPackMonitorSecondaryPackaging,
}
)
questions.append(
{
"item_name": "master_carton_weight",
"model": custom_models.EcoPackMonitorSecondaryPackaging,
"type": "text",
"validations": {
"datatype": "float",
"numeric_filter": {
"gte": 50,
"lte": 50000,
},
},
"helper_text_map": {"en": "Numbers only"},
}
)
return questions
autoform_navs.append(
{
"item_name": "secondary_packaging",
"label_map": {"en": "Secondary Packaging"},
"children": [
{
"category": "group",
"children": get_secondary_packaging_questions(),
"model": custom_models.EcoPackMonitorSecondaryPackaging,
"load_method": {
"function": "upsert",
"params": {
"key_fields": {
"ecopackmonitor_id": lambda monitor: monitor.id,
},
"defaults": {
"has_inner_polybag": {
"function": "get_child_item_value",
},
"master_carton_weight": {
"function": "get_child_item_value",
},
},
},
},
},
],
}
)
add_primary_packaging_tab(monitor)
add_secondary_packaging_tab()
# etc.
return autoform_navs
if __name__ == "__main__": # Check if script is being run directly and execute the following block if true
do_bulk_sync(
params={
"queryset": custom_models.Monitor.objects.all().order_by("id"), # queryset always on the Monitor model and used for both push and pull!
"language": lambda monitor: monitor.autoform_language if monitor.autoform_language else "en",
"sender_email": settings.EMAIL_USERNAME_SEND,
"workflows": {
"push": {
"keep_wip": True, # powerful feature to keep the work in progress (WIP) of the Autoform
"conditions": {
"start": lambda monitor.is_in_queue,
"refresh": lambda monitor: monitor.autoform_hash is None or monitor.to_be_refreshed,
"email": True, # high-level condition to control whether any email is sent (email-specific conditions are defined at email level below)
},
"emails": {
"initial_email": {
"condition": lambda monitor: monitor.sent is False,
"email_receivers": {
"to": get_email_receivers,
"cc": get_email_receivers_additional_cc,
},
"email_content": {
"subject": {
"en": lambda monitor: f"{settings.COMPANY_NAME} {monitor.suppliergroup.supplier_name} - {monitor.season} - {monitor.product.product_code} Cookie",
},
"body": {
"en": lambda monitor: f"""
<p>Dear <strong>{monitor.suppliergroup.supplier_name}</strong>,</p>
<br />
<p>You are expected to provide the information for your primary, secondary and tertiary packaging for reference <strong>{monitor.product.product_code}</strong> of <strong>{monitor.season}</strong>.</p>
<br />
<p>Please click on the link to open the form</p>
<p>{monitor.autoform_link_button}</p>
<br />
<p>We are expecting the form to be submitted before <strong style="color:#ff6384">{monitor.deadline_verbose}</strong>.</p>
<br />
<p>Thanks for your cooperation.</p>
<br />
<p>Best Regards,</p>
<p>Sourcing Team</p>
<p>{settings.COMPANY_NAME}</p>
""",
},
},
"procedures": [
lambda monitor: setattr(
monitor, "sent", True
),
set_sent_timestamp,
lambda monitor: setattr(
monitor,
"status",
"Pending",
),
],
},
"reminder_email": {
"condition": lambda monitor: monitor.reminder_sent is False,
"email_receivers": {
"to": get_email_receivers,
"cc": get_email_receivers_additional_cc,
},
"email_content": {
"subject": {
"en": lambda monitor: f"{monitor.suppliergroup.supplier_name} - {monitor.season} - {monitor.product.product_code} Cookie Reminder",
},
"body": {
"en": lambda monitor: f"""
<p>Dear <strong>{monitor.suppliergroup.supplier_name}</strong>,</p>
<br />
<p>You are reminded to provide the information for your primary, secondary and tertiary packaging for reference <strong>{monitor.product.product_code}</strong> of <strong>{monitor.season}</strong>.</p>
<br />
<p>Please click on the link to open the form</p>
<p>{monitor.autoform_link_button}</p>
<br />
<p>We are expecting the form to be submitted before <strong style="color:#ff6384">{monitor.deadline_verbose}</strong>.</p>
<br />
<p>Thank you for your cooperation.</p>
<br />
<p>Best Regards,</p>
<p>Sourcing Team</p>
<p>{settings.COMPANY_NAME}</p>
""",
},
},
"procedures": [
lambda monitor: setattr(
monitor, "reminder_sent ", False
),
set_sent_timestamp,
],
},
},
"procedures": {
"before_refresh": set_deadline,
"during_refresh": translate_autoform_config,
"after_refresh": [
lambda monitor: setattr(
monitor, "to_be_refreshed", False
),
lambda monitor: setattr(monitor, "autoform_loaded", False),
],
"before_email": set_monitor_email_variables,
"after_email": [
lambda monitor: setattr(
monitor,
"email_description_prefix",
"Email sent to",
),
create_ecopackmonitorevent,
],
"before_save": lambda monitor: setattr(
monitor, "is_in_queue", False
),
"after_save": None,
},
},
"pull": {
"conditions": {
"start": True,
"load": True,
"refresh": True, # to refresh the Autoform link right after loading
"opened_check": False,
"email": False,
},
"emails": {
"success": {
"condition": lambda monitor: monitor.autoform_loaded is True
and monitor.success_email_sent is False,
"email_content": {
"subject": {
"en": lambda monitor: f"Successful Submission of {monitor.season.name} Cookie Form - {monitor.suppliergroup.supplier_name} (ref:{monitor.product.product_code})",
},
"body": {
"en": lambda monitor: f"""
<p>Dear {monitor.suppliergroup.supplier_name},</p>
<p>Thank you for you submission.</p>
<p>
We have received the <strong>{monitor.season}</strong> <strong>Cookie Form</strong> for reference <strong>{monitor.product.product_code}</strong>
on <u>{monitor.sent_d}</u> at <u>{monitor.sent_t}</u> ({settings.TIME_ZONE} time)
for the <strong>{monitor.period}</strong>.
</p>
<p>{monitor.autoform_link_button_print}</p>
<p style="color:#36ebaa;">
No further action is required.
</p>
<p>Thank you!</p>
""",
},
},
}
},
"procedures": {
"before_load": None,
"during_load_label_value_list": None,
"during_load_table": None,
"after_load": [
lambda monitor: setattr(monitor, "autoform_loaded", True),
lambda monitor: setattr(monitor, "is_in_queue", True),
lambda monitor: setattr(
monitor,
"status",
"Accepted",
),
],
"before_email": None,
"after_email": [
lambda monitor: setattr(
monitor,
"email_description_prefix",
"Success email sent to",
),
create_ecopackmonitorevent,
],
"before_opened_check": None,
"after_opened_check": [
lambda monitor: setattr(
monitor,
"autoform_opened",
True,
),
lambda monitor: setattr(
monitor,
"status",
"Link Opened",
),
],
"before_save": [
set_monitor_status_and_stats,
],
"after_save": None,
},
},
},
"autoform_config": {
"autoform_frame": {
"chat": {
"active": True,
"application": "automail-lv-cookie",
"module": "Cookie Module",
"context": "This is for suppliers to declare all the packaging they have used in the 1 specified product.",
},
"stage": "prod",
"keep_open": True,
"grid": "neat",
"logo": "static/uploads/Lineverge/logo.png",
"logo_width": "120px",
"title_map": {
"en": "Cookie",
},
"subtitle": lambda monitor: f"""
<strong>{monitor.suppliergroup.supplier_name}</strong><br />
{monitor.season} - {monitor.product.product_code}
""",
"description_map": {"en": f"Please select all the items you use in your packaging."},
"successful_submit_subtitle_map": {
"en": "Your answers have been submitted, the form will stay open in case you need to make further changes. <br/><br/>Redirecting in 10 seconds... <meta http-equiv='refresh' content='10'>",
},
"successful_submit_description_map": {
"en": f"For questions or support please contact your contact point.",
},
"languages": [
{"code": "en", "label": "English"},
{"code": "cn", "label": "ç®€ä½“ä¸æ–‡"},
{"code": "tr", "label": "Türk"},
],
"downloads": [],
},
"autoform_lists": {
"hanger_reference_options_config": get_hanger_reference_options_config(),
},
"autoform_navs": get_autoform_navs,
},
},
)Important design considerations
Autoform Nav ElementsLast updated