2 İşlemeler ff977e3592 ... 2a21324974

Yazar SHA1 Mesaj Tarih
  alvesantos 2a21324974 feat: add down payment and demonstrative values to contract dialog 2 gün önce
  alvesantos 36cf310a43 fix: add Qtd. Aulas field to Proposta Comercial dialog 2 gün önce

+ 15 - 1
src/pages/packages/components/AddEditPackageDialog.vue

@@ -41,6 +41,16 @@
                     />
 
 
+                    <DefaultInput
+                      v-model="form.quantity_classes"
+                      v-model:error="validationErrors.quantity_classes"
+                      class="col-12"
+                      label="Qtd. Aulas"
+                      type="number"
+                      :min="1"
+                      :rules="[inputRules.required, inputRules.minValue(1)]"
+                    />
+
                     <DefaultInput
                       v-model="form.class_duration_hours"
                       v-model:error="validationErrors.class_duration_minutes"
@@ -209,6 +219,7 @@ const { form, getUpdatedFields } = useForm({
   name: props.package?.name ?? null,
   pavao: defaultPricingBlock(),
   pavao_enabled: false,
+  quantity_classes: props.package?.quantity_classes ?? null,
 });
 
 const {
@@ -285,6 +296,7 @@ const onOKClick = async () => {
 
     name: form.name,
     pavao: form.pavao_enabled ? toPricingPayload(form.pavao) : null,
+    quantity_classes: Number(form.quantity_classes) || null,
   };
 
   try {
@@ -296,7 +308,7 @@ const onOKClick = async () => {
       const changedFields = getUpdatedFields.value;
       const updatePayload = {};
 
-      const directKeys = ["name"];
+      const directKeys = ["name", "quantity_classes"];
 
       for (const key of directKeys) {
         if (key in changedFields) {
@@ -346,6 +358,8 @@ onMounted(async () => {
   form.class_duration_hours =
     (packageData.class_duration_minutes ?? 120) / 60;
 
+  form.quantity_classes = packageData.quantity_classes ?? null;
+
   form.pavao_enabled = !!packageData.pavao;
   form.irrecusavel_enabled = !!packageData.irrecusavel;
 

+ 78 - 1
src/pages/students/components/AddEditContractDialog.vue

@@ -329,6 +329,45 @@
               </div>
 
               <div class="row q-col-gutter-sm">
+                <div class="col-3">
+                  <DefaultCurrencyInput
+                    :model-value="form.classes_value"
+                    disable
+                    label="Valor da Aula"
+                  />
+                </div>
+
+                <div class="col-3">
+                  <DefaultCurrencyInput
+                    :model-value="form.materials_total_value"
+                    disable
+                    label="Valor dos Materiais"
+                  />
+                </div>
+
+                <div class="col-3">
+                  <DefaultCurrencyInput
+                    v-model="form.down_payment_value"
+                    v-model:error="validationErrors.down_payment_value"
+                    label="Taxa de Contratação / Entrada"
+                  />
+                </div>
+
+                <div class="col-3">
+                  <DefaultInputDatePicker
+                    v-model="form.down_payment_date"
+                    v-model:error="validationErrors.down_payment_date"
+                    label="Data do Valor"
+                    :rules="
+                      form.down_payment_value
+                        ? [inputRules.required, inputRules.date]
+                        : [inputRules.date]
+                    "
+                  />
+                </div>
+              </div>
+
+              <div class="row q-col-gutter-sm q-mt-xs">
                 <div class="col-3">
                   <DefaultCurrencyInput
                     v-model="form.total_value"
@@ -548,7 +587,10 @@ const totalInstallmentValue = computed(() => {
     return null;
   }
 
-  return Number((form.total_value / form.total_installments).toFixed(2));
+  const downPayment = Number(form.down_payment_value) || 0;
+  const remaining = Math.max(0, form.total_value - downPayment);
+
+  return Number((remaining / form.total_installments).toFixed(2));
 });
 
 const modalityOptions = computed(() => {
@@ -638,13 +680,18 @@ const trimTime = (time) => (time ? time.slice(0, 5) : null);
 
 const { form, getUpdatedFields } = useForm({
   class_quantity: props.contract?.class_quantity ?? null,
+  classes_value: null,
   due_day: props.contract?.due_day ?? null,
 
+  down_payment_date: props.contract?.down_payment_date ?? null,
+  down_payment_value: props.contract?.down_payment_value ?? null,
+
   end_date: props.contract?.end_date ?? defaultContractDates?.end_date ?? null,
 
   end_time: trimTime(props.contract?.end_time),
 
   late_fee: props.contract?.fine_cancelled ?? null,
+  materials_total_value: props.contract?.materials_value ?? null,
   package_id: props.contract?.class_package_unit_id ?? null,
 
   payment_method: props.contract?.payment_method ?? null,
@@ -715,6 +762,11 @@ const buildPayload = () => ({
   class_package_unit_id: form.package_id,
   class_quantity: form.class_quantity,
 
+  down_payment_date: form.down_payment_date
+    ? formatDateDMYtoYMD(form.down_payment_date)
+    : null,
+  down_payment_value: form.down_payment_value,
+
   due_day: form.due_day ? Number.parseInt(form.due_day) : null,
 
   end_date: form.end_date ? formatDateDMYtoYMD(form.end_date) : null,
@@ -807,6 +859,7 @@ const handleSave = async () => {
       "pricing_mode",
       "total_value",
       "total_installments",
+      "down_payment_value",
     ]) {
       if (key in changedFields) {
         updatePayload[key] = payload[key];
@@ -823,6 +876,7 @@ const handleSave = async () => {
       "signature_date",
       "end_date",
       "total_due_date",
+      "down_payment_date",
     ]) {
       if (key in changedFields) {
         updatePayload[key] = payload[key];
@@ -1048,12 +1102,16 @@ watch(
     if (!modality) {
       form.total_value = null;
       form.total_installments = null;
+      form.classes_value = null;
+      form.materials_total_value = null;
 
       return;
     }
 
     form.total_value = modality.total_value;
     form.total_installments = modality.total_max_installments;
+    form.classes_value = modality.classes_value;
+    form.materials_total_value = modality.materials_total_value;
   },
 );
 
@@ -1141,6 +1199,25 @@ onMounted(async () => {
 
   packages.value = unitPackages;
 
+  // Num contrato existente o pacote já vem selecionado, então o watch de
+  // package_id/pricing_mode não dispara sozinho — busca a modalidade aqui
+  // pra preencher os campos demonstrativos (Valor da Aula/Materiais).
+  if (props.contract) {
+    const selectedPackage = packages.value.find(
+      (item) => item.id === form.package_id,
+    );
+
+    const modality =
+      form.pricing_mode === "irrecusavel"
+        ? selectedPackage?.irrecusavel
+        : selectedPackage?.pavao;
+
+    if (modality) {
+      form.classes_value = modality.classes_value;
+      form.materials_total_value ??= modality.materials_total_value;
+    }
+  }
+
   unitDetails.value = unitData ?? store.selectedUnit ?? {};
 
   isAutomaticProtocol.value = unitDetails.value?.automatic_protocol ?? true;