FinancialTab.vue 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <template>
  2. <div class="financial-tab q-pa-md">
  3. <DefaultForm ref="formRef" class="unit-tab-form" @submit="onSave">
  4. <q-scroll-area ref="scrollAreaRef" class="unit-form-tab-scroll-area">
  5. <div class="column q-gutter-lg">
  6. <div>
  7. <div class="text-subtitle1 text-weight-medium q-mb-sm">
  8. Dados Bancários
  9. </div>
  10. <div class="row q-col-gutter-md">
  11. <DefaultInput
  12. v-model="form.account_holder"
  13. v-model:error="validationErrors.account_holder"
  14. class="col-12 col-md-4"
  15. label="Titular da Conta"
  16. outlined
  17. :error-message="validationErrors.account_holder"
  18. />
  19. <DefaultInput
  20. v-model="form.agency"
  21. v-model:error="validationErrors.agency"
  22. class="col-12 col-md-4"
  23. label="Agência"
  24. outlined
  25. :error-message="validationErrors.agency"
  26. />
  27. <DefaultInput
  28. v-model="form.account"
  29. v-model:error="validationErrors.account"
  30. class="col-12 col-md-4"
  31. label="Conta"
  32. outlined
  33. :error-message="validationErrors.account"
  34. />
  35. <DefaultInput
  36. v-model="form.bank"
  37. v-model:error="validationErrors.bank"
  38. class="col-12 col-md-3"
  39. label="Banco"
  40. outlined
  41. :error-message="validationErrors.bank"
  42. />
  43. <DefaultInput
  44. v-model="form.pix_key"
  45. v-model:error="validationErrors.pix_key"
  46. class="col-12 col-md-3"
  47. label="Chave Pix"
  48. outlined
  49. :error-message="validationErrors.pix_key"
  50. />
  51. <DefaultSelect
  52. v-model="form.tax_regime"
  53. v-model:error="validationErrors.tax_regime"
  54. class="col-12 col-md-3"
  55. emit-value
  56. label="Regime Tributário"
  57. map-options
  58. outlined
  59. :error-message="validationErrors.tax_regime"
  60. :options="taxRegimeOptions"
  61. />
  62. <DefaultSelect
  63. v-model="form.account_type"
  64. v-model:error="validationErrors.account_type"
  65. class="col-12 col-md-3"
  66. emit-value
  67. label="Tipo de Conta"
  68. map-options
  69. outlined
  70. :error-message="validationErrors.account_type"
  71. :options="accountTypeOptions"
  72. />
  73. </div>
  74. </div>
  75. <div>
  76. <div class="text-subtitle1 text-weight-medium q-mb-sm">
  77. Dados para Faturamento
  78. </div>
  79. <div class="row q-col-gutter-md">
  80. <DefaultSelect
  81. v-model="form.billing_method"
  82. v-model:error="validationErrors.billing_method"
  83. class="col-12 col-md-6"
  84. emit-value
  85. label="Forma de Cobrança"
  86. map-options
  87. outlined
  88. :error-message="validationErrors.billing_method"
  89. :options="billingMethodOptions"
  90. />
  91. <DefaultInputDatePicker
  92. v-model="form.due_date"
  93. v-model:error="validationErrors.due_date"
  94. class="col-12 col-md-6"
  95. label="Data de Vencimento"
  96. :error-message="validationErrors.due_date"
  97. />
  98. <DefaultInput
  99. v-model="form.financial_email"
  100. v-model:error="validationErrors.financial_email"
  101. class="col-12"
  102. label="E-mail Financeiro"
  103. outlined
  104. :error-message="validationErrors.financial_email"
  105. :rules="[inputRules.email]"
  106. />
  107. </div>
  108. </div>
  109. <div>
  110. <div class="text-subtitle1 text-weight-medium q-mb-sm">
  111. Contratos
  112. </div>
  113. <div class="row q-col-gutter-md">
  114. <DefaultInput
  115. v-model.number="form.max_freeze_count"
  116. v-model:error="validationErrors.max_freeze_count"
  117. class="col-12 col-md-4"
  118. label="Máximo de Meses para Trancar"
  119. outlined
  120. type="number"
  121. :error-message="validationErrors.max_freeze_count"
  122. :rules="[inputRules.minValue(0)]"
  123. />
  124. <DefaultInput
  125. v-model.number="form.default_discount"
  126. v-model:error="validationErrors.default_discount"
  127. class="col-12 col-md-4"
  128. label="Desconto Padrão (%)"
  129. outlined
  130. type="number"
  131. :error-message="validationErrors.default_discount"
  132. :rules="[inputRules.minValue(0), inputRules.maxValue(100)]"
  133. />
  134. <DefaultInput
  135. v-model.number="form.default_interest"
  136. v-model:error="validationErrors.default_interest"
  137. class="col-12 col-md-4"
  138. label="Juros Padrão (% a.m.)"
  139. outlined
  140. type="number"
  141. :error-message="validationErrors.default_interest"
  142. :rules="[inputRules.minValue(0)]"
  143. />
  144. <DefaultInput
  145. v-model.number="form.default_fine"
  146. v-model:error="validationErrors.default_fine"
  147. class="col-12 col-md-4"
  148. label="Multa Padrão (%)"
  149. outlined
  150. type="number"
  151. :error-message="validationErrors.default_fine"
  152. :rules="[inputRules.minValue(0), inputRules.maxValue(100)]"
  153. />
  154. <div class="col-12 col-md-4 flex items-center">
  155. <q-toggle
  156. v-model="form.charge_roi"
  157. color="primary"
  158. label="Cobrar ROI"
  159. />
  160. </div>
  161. <div class="col-12 col-md-4 flex items-center">
  162. <q-toggle
  163. v-model="form.charge_fnm"
  164. color="primary"
  165. label="Cobrar FNM"
  166. />
  167. </div>
  168. </div>
  169. </div>
  170. </div>
  171. </q-scroll-area>
  172. <q-separator />
  173. <div class="row justify-end q-gutter-sm q-pt-md">
  174. <q-btn
  175. color="negative"
  176. label="Cancelar"
  177. no-caps
  178. outline
  179. @click="resetForm"
  180. />
  181. <q-btn
  182. color="primary"
  183. label="Salvar"
  184. no-caps
  185. type="submit"
  186. unelevated
  187. :loading="loading"
  188. />
  189. </div>
  190. </DefaultForm>
  191. </div>
  192. </template>
  193. <script setup>
  194. import {
  195. getFinancialByUnit,
  196. upsertFinancial,
  197. } from "src/api/unit_financial";
  198. import { onMounted, ref } from "vue";
  199. import { useForm } from "src/composables/useForm";
  200. import { useInputRules } from "src/composables/useInputRules";
  201. import { useScroll } from "src/composables/useScroll";
  202. import { useSubmitHandler } from "src/composables/useSubmitHandler";
  203. import DefaultInput from "src/components/defaults/DefaultInput.vue";
  204. import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
  205. import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
  206. const props = defineProps({
  207. unitId: {
  208. default: null,
  209. type: Number,
  210. },
  211. });
  212. const { inputRules } = useInputRules();
  213. const { scrollToComponent } = useScroll();
  214. const formRef = ref(null);
  215. const scrollAreaRef = ref(null);
  216. const { form, getUpdatedFields, resetUpdateForm, setUpdateFormAsOriginal } =
  217. useForm(
  218. {
  219. account: null,
  220. account_holder: null,
  221. account_type: null,
  222. agency: null,
  223. bank: null,
  224. billing_method: null,
  225. charge_fnm: true,
  226. charge_roi: true,
  227. default_discount: null,
  228. default_fine: null,
  229. default_interest: null,
  230. due_date: null,
  231. financial_email: null,
  232. max_freeze_count: null,
  233. pix_key: null,
  234. tax_regime: null,
  235. },
  236. { containerRef: scrollAreaRef },
  237. );
  238. const {
  239. loading,
  240. validationErrors,
  241. execute,
  242. } = useSubmitHandler({
  243. containerRef: scrollAreaRef,
  244. formRef,
  245. onSuccess: (saved) => {
  246. Object.assign(form, saved);
  247. setUpdateFormAsOriginal();
  248. },
  249. scrollFn: scrollToComponent,
  250. });
  251. const accountTypeOptions = [
  252. { label: "Selecione", value: null },
  253. { label: "Conta Corrente", value: "corrente" },
  254. { label: "Conta Poupança", value: "poupanca" },
  255. ];
  256. const billingMethodOptions = [
  257. { label: "Selecione", value: null },
  258. { label: "Boleto", value: "boleto" },
  259. { label: "Débito Automático", value: "debit" },
  260. { label: "PIX", value: "pix" },
  261. { label: "Cartão de Crédito", value: "credit_card" },
  262. ];
  263. const taxRegimeOptions = [
  264. { label: "Selecione", value: null },
  265. { label: "Simples Nacional", value: "simples_nacional" },
  266. { label: "Lucro Presumido", value: "lucro_presumido" },
  267. { label: "Lucro Real", value: "lucro_real" },
  268. { label: "MEI", value: "mei" },
  269. ];
  270. const fetchData = async () => {
  271. if (!props.unitId) return;
  272. await loadFinancial();
  273. };
  274. const loadFinancial = async () => {
  275. try {
  276. const data = await getFinancialByUnit(props.unitId);
  277. if (data) {
  278. Object.assign(form, data);
  279. setUpdateFormAsOriginal();
  280. }
  281. } catch (error) {
  282. console.error(error);
  283. }
  284. };
  285. const onSave = async () => {
  286. if (!props.unitId) return;
  287. await execute(() =>
  288. upsertFinancial({
  289. unit_id: props.unitId,
  290. ...getUpdatedFields.value,
  291. }),
  292. );
  293. };
  294. const resetForm = () => {
  295. resetUpdateForm();
  296. };
  297. onMounted(fetchData);
  298. </script>
  299. <style scoped>
  300. .financial-tab {
  301. box-sizing: border-box;
  302. min-height: 0;
  303. }
  304. .unit-tab-form {
  305. display: flex;
  306. flex-direction: column;
  307. height: 100%;
  308. min-height: 0;
  309. }
  310. .unit-form-tab-scroll-area {
  311. flex: 1 1 auto;
  312. min-height: 0;
  313. }
  314. </style>