CreateContractDialog.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <template>
  2. <q-dialog ref="dialogRef" @hide="onDialogHide">
  3. <q-card
  4. class="q-dialog-plugin overflow-hidden"
  5. style="width: 100%; max-width: 1100px"
  6. >
  7. <DefaultDialogHeader
  8. :title="'Criar novo contrato'"
  9. @close="onDialogCancel"
  10. />
  11. <q-card-section>
  12. <div class="text-body2 q-mb-sm">Dados da Unidade</div>
  13. <div class="row q-col-gutter-sm">
  14. <DefaultInput
  15. :model-value="unitData.name"
  16. label="Nome da Unidade"
  17. color="secondary"
  18. label-color="secondary"
  19. class="col-md-6 col-12"
  20. readonly
  21. />
  22. <DefaultInput
  23. :model-value="unitData.cnpj"
  24. label="CNPJ"
  25. color="secondary"
  26. label-color="secondary"
  27. class="col-md-3 col-12"
  28. :mask="masks.Brasil.cnpj"
  29. :rules="[inputRules.cnpj]"
  30. readonly
  31. />
  32. <DefaultInput
  33. :model-value="unitData.id"
  34. label="ID"
  35. color="secondary"
  36. label-color="secondary"
  37. class="col-md-3 col-12"
  38. disable
  39. />
  40. <DefaultInput
  41. :model-value="unitData.franchisee_name"
  42. label="Nome do Franqueado"
  43. color="secondary"
  44. label-color="secondary"
  45. class="col-md-4 col-12"
  46. disable
  47. />
  48. <DefaultInput
  49. :model-value="unitData.franchisee_document"
  50. label="CPF"
  51. color="secondary"
  52. label-color="secondary"
  53. class="col-md-4 col-12"
  54. :mask="masks.Brasil.cpf"
  55. :rules="[inputRules.cpf]"
  56. disable
  57. />
  58. <DefaultInput
  59. :model-value="unitData.franchisee_birthday"
  60. label="Data de Nascimento"
  61. color="secondary"
  62. label-color="secondary"
  63. class="col-md-4 col-12"
  64. disable
  65. />
  66. </div>
  67. </q-card-section>
  68. <q-card-section>
  69. <div class="text-body2 q-mb-sm">Definir Valores e TBR</div>
  70. <div class="row q-col-gutter-sm">
  71. <DefaultInputDatePicker
  72. v-model:untreated-date="contractForm.start_date"
  73. label="Data de Início"
  74. color="secondary"
  75. label-color="secondary"
  76. class="col-md-3 col-12"
  77. />
  78. <DefaultInputDatePicker
  79. v-model:untreated-date="contractForm.end_date"
  80. label="Data de Fim"
  81. color="secondary"
  82. label-color="secondary"
  83. class="col-md-3 col-12"
  84. />
  85. <DefaultCurrencyInput
  86. v-model="contractForm.tbr_fixed_value"
  87. label="TBR $"
  88. color="secondary"
  89. label-color="secondary"
  90. class="col-md-3 col-12"
  91. />
  92. <DefaultInput
  93. v-model="contractForm.invoice_due_date"
  94. label="Dia de Vencimento do Boleto"
  95. color="secondary"
  96. label-color="secondary"
  97. type="number"
  98. class="col-md-3 col-12"
  99. >
  100. </DefaultInput>
  101. <DefaultSelect
  102. v-model="contractForm.municipality_size_id"
  103. label="Faixa de Habitante"
  104. color="secondary"
  105. label-color="secondary"
  106. :options="municipalitySizeOptions"
  107. emit-value
  108. map-options
  109. use-input
  110. fill-input
  111. hide-selected
  112. input-debounce="0"
  113. class="col-md-3 col-12"
  114. />
  115. <DefaultInput
  116. v-model="contractForm.tax_base_royalts"
  117. label="Taxa Base Royalties"
  118. color="secondary"
  119. label-color="secondary"
  120. type="number"
  121. class="col-md-3 col-12"
  122. >
  123. <template #append>
  124. <span class="text-secondary">%</span>
  125. </template>
  126. </DefaultInput>
  127. <DefaultInput
  128. v-model="contractForm.tax_base_fnm"
  129. label="Taxa Base FMN"
  130. color="secondary"
  131. label-color="secondary"
  132. type="number"
  133. class="col-md-3 col-12"
  134. >
  135. <template #append>
  136. <span class="text-secondary">%</span>
  137. </template>
  138. </DefaultInput>
  139. <DefaultInput
  140. v-model="contractForm.tax_base_maintenance"
  141. label="Taxa Base Manutenção"
  142. color="secondary"
  143. label-color="secondary"
  144. type="number"
  145. class="col-md-3 col-12"
  146. >
  147. <template #append>
  148. <span class="text-secondary">%</span>
  149. </template>
  150. </DefaultInput>
  151. </div>
  152. </q-card-section>
  153. <q-card-actions align="right">
  154. <q-btn
  155. outline
  156. color="primary"
  157. label="Cancelar"
  158. @click="onDialogCancel"
  159. />
  160. <q-btn color="primary" label="Salvar" :loading="saving" @click="save" />
  161. </q-card-actions>
  162. </q-card>
  163. </q-dialog>
  164. </template>
  165. <script setup>
  166. import { ref, reactive, onMounted } from "vue";
  167. import { useDialogPluginComponent } from "quasar";
  168. import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
  169. import DefaultInput from "src/components/defaults/DefaultInput.vue";
  170. import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
  171. import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
  172. import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
  173. import masks from "src/helpers/masks";
  174. import { useInputRules } from "src/composables/useInputRules";
  175. import { getUnit } from "src/api/unit";
  176. import { getLatestTbr } from "src/api/tbr";
  177. import { getMunicipalitySizes } from "src/api/tbr_calculation";
  178. import { createFranchiseeContract } from "src/api/franchisee_contract";
  179. defineEmits([...useDialogPluginComponent.emits]);
  180. const props = defineProps({
  181. unitId: {
  182. type: Number,
  183. required: true,
  184. },
  185. });
  186. const { dialogRef, onDialogHide, onDialogCancel, onDialogOK } =
  187. useDialogPluginComponent();
  188. const saving = ref(false);
  189. const municipalitySizeOptions = ref([]);
  190. const { inputRules } = useInputRules();
  191. const unitData = reactive({
  192. id: null,
  193. name: null,
  194. cnpj: null,
  195. franchisee_name: null,
  196. franchisee_document: null,
  197. franchisee_birthday: null,
  198. });
  199. const contractForm = reactive({
  200. start_date: null,
  201. end_date: null,
  202. tbr_fixed_value: null,
  203. invoice_due_date: null,
  204. municipality_size_id: null,
  205. tax_base_royalts: null,
  206. tax_base_fnm: null,
  207. tax_base_maintenance: null,
  208. });
  209. async function loadData() {
  210. const [unit, latestTbr, sizes] = await Promise.all([
  211. getUnit(props.unitId),
  212. getLatestTbr(),
  213. getMunicipalitySizes(),
  214. ]);
  215. unitData.id = unit.id;
  216. unitData.name = unit.name;
  217. unitData.cnpj = unit.cnpj;
  218. unitData.franchisee_name = unit.name_responsible;
  219. const firstPartner = unit.partners?.[0];
  220. if (firstPartner) {
  221. unitData.franchisee_document = firstPartner.cpf;
  222. unitData.franchisee_birthday = firstPartner.birth_date;
  223. }
  224. if (latestTbr) {
  225. contractForm.tbr_fixed_value = parseFloat(latestTbr.tbr_value);
  226. contractForm.tax_base_royalts = parseFloat(
  227. (latestTbr.royalties_percentage * 100).toFixed(4),
  228. );
  229. contractForm.tax_base_fnm = parseFloat(
  230. (latestTbr.fnm_percentage * 100).toFixed(4),
  231. );
  232. contractForm.tax_base_maintenance = parseFloat(
  233. (latestTbr.maintenance_percentage * 100).toFixed(4),
  234. );
  235. }
  236. municipalitySizeOptions.value = (sizes ?? []).map((s) => ({
  237. label: s.description,
  238. value: s.id,
  239. }));
  240. }
  241. async function save() {
  242. saving.value = true;
  243. try {
  244. await createFranchiseeContract({
  245. unit_id: props.unitId,
  246. start_date: contractForm.start_date,
  247. end_date: contractForm.end_date,
  248. tbr_fixed_value: contractForm.tbr_fixed_value,
  249. invoice_due_date: contractForm.invoice_due_date,
  250. municipality_size_id: contractForm.municipality_size_id,
  251. tbr_fixed_value_percentage:
  252. contractForm.tax_base_royalts != null
  253. ? contractForm.tax_base_royalts / 100
  254. : null,
  255. marketing_fund_percentage:
  256. contractForm.tax_base_fnm != null
  257. ? contractForm.tax_base_fnm / 100
  258. : null,
  259. maintance_tax_percentage:
  260. contractForm.tax_base_maintenance != null
  261. ? contractForm.tax_base_maintenance / 100
  262. : null,
  263. });
  264. onDialogOK();
  265. } catch (error) {
  266. console.error(error);
  267. } finally {
  268. saving.value = false;
  269. }
  270. }
  271. onMounted(loadData);
  272. </script>