Selaa lähdekoodia

fix the cpr sender (need fx the collateral_typecode)

gdias 2 viikkoa sitten
vanhempi
sitoutus
f7086e6e68
2 muutettua tiedostoa jossa 157 lisäystä ja 4 poistoa
  1. 143 1
      src/lib/components/commodities/cpr/EmissionCpr.svelte
  2. 14 3
      src/routes/cpr/+page.svelte

+ 143 - 1
src/lib/components/commodities/cpr/EmissionCpr.svelte

@@ -1,5 +1,8 @@
 <script>
   import { onMount } from 'svelte';
+  import { get } from 'svelte/store';
+
+  import { authToken } from '$lib/utils/stores';
 
   export let formData = {};
   export let onFieldChange = () => {};
@@ -22,6 +25,10 @@
   const ISSUER_CITY_FIELD = 'cpr_issuers_city_name';
   const CIDADES_ESTADOS_SRC = 'https://cdn.jsdelivr.net/npm/cidades-estados@1.4.1/cidades-estados.js';
   const isBrowser = typeof window !== 'undefined';
+  const apiUrl = import.meta.env.VITE_API_URL;
+
+  const PRODUCT_NAME_FIELD = 'cpr_product_name';
+  const PRODUCT_CLASS_FIELD = 'cpr_product_class_name';
 
   let estadosOptions = [];
   let cidadesPorEstado = {};
@@ -31,6 +38,13 @@
   let selectedCityValue = '';
   let availableCities = [];
 
+  let commodityOptions = [];
+  let commoditiesLoading = false;
+  let commoditiesError = '';
+  let currentProductValue = '';
+  let selectedCommodityOption = null;
+  let selectedCommodityId = '';
+
   const sections = [
     {
       title: 'Emissão e Entrega',
@@ -59,7 +73,6 @@
       columns: 3,
       fields: [
         { key: 'cpr_product_name', label: 'Produto' },
-        { key: 'cpr_product_class_name', label: 'Classe' },
         { key: 'cpr_product_harvest', label: 'Safra' },
         { key: 'cpr_product_quantity', label: 'Quantidade' },
         { key: 'cpr_measure_unit_name', label: 'Unidade de medida' },
@@ -86,6 +99,7 @@
   onMount(() => {
     if (!isBrowser) return;
     hydrateCidadesEstadosOptions();
+    void fetchCommodityOptions();
   });
 
   $: selectedStateValue = formData?.[STATE_FIELD] ?? '';
@@ -94,6 +108,11 @@
     selectedStateValue && cidadesPorEstado[selectedStateValue]
       ? cidadesPorEstado[selectedStateValue]
       : [];
+  $: currentProductValue = formData?.[PRODUCT_NAME_FIELD] ?? '';
+  $: selectedCommodityOption =
+    commodityOptions.find((item) => item.name === currentProductValue) ?? null;
+  $: selectedCommodityId = selectedCommodityOption?.id ?? '';
+  $: synchronizeProductCommodityFields(selectedCommodityOption);
 
   async function hydrateCidadesEstadosOptions() {
     try {
@@ -122,6 +141,69 @@
     }
   }
 
+  async function fetchCommodityOptions() {
+    if (!apiUrl) {
+      commoditiesError = 'URL da API não configurada.';
+      return;
+    }
+
+    commoditiesLoading = true;
+    commoditiesError = '';
+    try {
+      const token = resolveAuthToken();
+      if (!token) {
+        throw new Error('Sessão expirada. Faça login novamente.');
+      }
+      const res = await fetch(`${apiUrl}/commodities/get`, {
+        method: 'POST',
+        headers: {
+          'content-type': 'application/json',
+          Authorization: `Bearer ${token}`
+        },
+        body: JSON.stringify({})
+      });
+
+      let payload = null;
+      try {
+        payload = await res.json();
+      } catch (err) {
+        console.error('Falha ao interpretar resposta de /commodities/get:', err);
+      }
+
+      if (!res.ok || payload?.status !== 'ok') {
+        throw new Error(payload?.msg ?? 'Falha ao carregar commodities.');
+      }
+
+      commodityOptions = Array.isArray(payload?.data)
+        ? payload.data
+            .map((item) => ({
+              id:
+                item?.commodities_id != null
+                  ? String(item.commodities_id)
+                  : item?.commodities_name ?? '',
+              name: (item?.commodities_name ?? '').trim(),
+              class: (item?.commodities_class ?? '').trim(),
+              raw: item
+            }))
+            .filter((item) => item.id && item.name)
+        : [];
+    } catch (error) {
+      console.error('Erro ao carregar commodities (CPR):', error);
+      commoditiesError = error?.message ?? 'Falha ao carregar commodities.';
+      commodityOptions = [];
+    } finally {
+      commoditiesLoading = false;
+    }
+  }
+
+  function resolveAuthToken() {
+    const storeToken = get(authToken);
+    if (storeToken) return storeToken;
+    if (!isBrowser) return null;
+    const match = document.cookie.match(/(?:^|; )auth_token=([^;]+)/);
+    return match ? decodeURIComponent(match[1]) : null;
+  }
+
   function loadCidadesEstadosScript() {
     if (!isBrowser) {
       return Promise.reject(new Error('Ambiente indisponível para carregar cidades-estados.'));
@@ -210,6 +292,37 @@
   function handleRepeatingCityChange(groupKey, index, cityField, value) {
     onRepeatingFieldChange(groupKey, index, cityField, value);
   }
+
+  function isProductField(key) {
+    return key === PRODUCT_NAME_FIELD;
+  }
+
+  function synchronizeProductCommodityFields(option) {
+    if (!option) {
+      const hasClassValue = Boolean(formData?.[PRODUCT_CLASS_FIELD]);
+      if (!currentProductValue && hasClassValue) {
+        onFieldChange(PRODUCT_CLASS_FIELD, '');
+      }
+      return;
+    }
+
+    const resolvedName = option.name ?? '';
+    if (resolvedName && formData?.[PRODUCT_NAME_FIELD] !== resolvedName) {
+      onFieldChange(PRODUCT_NAME_FIELD, resolvedName);
+    }
+
+    const resolvedClass = option.class ?? '';
+    if (formData?.[PRODUCT_CLASS_FIELD] !== resolvedClass) {
+      onFieldChange(PRODUCT_CLASS_FIELD, resolvedClass);
+    }
+  }
+
+  function handleProductSelect(event) {
+    const commodityId = event?.currentTarget?.value ?? '';
+    const selected = commodityOptions.find((item) => item.id === commodityId) ?? null;
+    onFieldChange(PRODUCT_NAME_FIELD, selected?.name ?? '');
+    onFieldChange(PRODUCT_CLASS_FIELD, selected?.class ?? '');
+  }
 </script>
 
 <div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
@@ -272,6 +385,35 @@
                 {#if estadosErro}
                   <p class="text-xs text-red-500 mt-1">{estadosErro}</p>
                 {/if}
+              {:else if isProductField(field.key)}
+                <select
+                  class="w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-100 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:cursor-not-allowed disabled:opacity-60"
+                  value={selectedCommodityId}
+                  on:change={handleProductSelect}
+                  required={requiredFields?.has(field.key)}
+                  disabled={commoditiesLoading || !!commoditiesError}
+                >
+                  <option value="">
+                    {#if commoditiesLoading}
+                      Carregando produtos...
+                    {:else if commoditiesError}
+                      Não foi possível carregar
+                    {:else}
+                      Selecione um produto
+                    {/if}
+                  </option>
+                  {#each commodityOptions as commodity}
+                    <option value={commodity.id}>
+                      {commodity.name}
+                      {#if commodity.class}
+                        — Classe {commodity.class}
+                      {/if}
+                    </option>
+                  {/each}
+                </select>
+                {#if commoditiesError}
+                  <p class="text-xs text-red-500 mt-1">{commoditiesError}</p>
+                {/if}
               {:else if field.type === 'select'}
                 <select
                   class="w-full rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700/70 text-gray-900 dark:text-gray-100 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"

+ 14 - 3
src/routes/cpr/+page.svelte

@@ -585,13 +585,24 @@
         console.error('[CPR] Resposta inválida ao confirmar pagamento:', err, raw);
       }
     }
-    if (res.ok && body?.success) {
+    const isSuccessResponse = Boolean(body?.success || body?.status === 'ok');
+    if (res.ok && isSuccessResponse) {
+      console.log('[CPR] Confirmação de pagamento bem-sucedida:', body);
       return { state: 'success', data: body };
     }
     const code = body?.code ?? body?.error;
     const backendMessage = body?.message ?? body?.msg ?? body?.data?.message ?? raw ?? '';
-    if (code === 'E_PAYMENT_PENDING' || body?.data?.status === 0) {
-      return { state: 'pending', message: 'Pagamento pendente. Assim que confirmado, você será avisado.' };
+    const backendMessageText = typeof backendMessage === 'string' ? backendMessage.trim() : '';
+    const isKnownPending =
+      code === 'E_PAYMENT_PENDING' ||
+      body?.data?.status === 0 ||
+      res.status === 409 ||
+      backendMessageText.toLowerCase?.().includes('pagamento ainda não confirmado');
+    if (isKnownPending) {
+      return {
+        state: 'pending',
+        message: backendMessageText || 'Pagamento pendente. Assim que confirmado, você será avisado.'
+      };
     }
     const normalizedBackendMessage = typeof backendMessage === 'string' ? backendMessage.trim() : '';
     const normalizedRaw = typeof raw === 'string' ? raw.trim() : '';